mirror of https://github.com/ethereum/go-ethereum
The Azure SDK doesn't support Go 1.5 anymore. We can't upgrade it until Go 1.8 comes out.pull/3546/head
parent
02b67558e8
commit
d78f9b834a
@ -1,26 +0,0 @@ |
|||||||
#!/usr/bin/env perl6 |
|
||||||
|
|
||||||
use v6; |
|
||||||
|
|
||||||
my $copyright = '// Copyright 2016 Zack Guo <gizak@icloud.com>. All rights reserved. |
|
||||||
// Use of this source code is governed by a MIT license that can |
|
||||||
// be found in the LICENSE file. |
|
||||||
|
|
||||||
'; |
|
||||||
|
|
||||||
sub MAIN('update-docstr', Str $srcp) { |
|
||||||
if $srcp.IO.f { |
|
||||||
$_ = $srcp.IO.slurp; |
|
||||||
if m/^ \/\/\s Copyright .+? \n\n/ { |
|
||||||
unless ~$/ eq $copyright { |
|
||||||
s/^ \/\/\s Copyright .+? \n\n /$copyright/; |
|
||||||
spurt $srcp, $_; |
|
||||||
say "[updated] doc string for:"~$srcp; |
|
||||||
} |
|
||||||
} else { |
|
||||||
say "[added] doc string for "~$srcp~" (no match found)"; |
|
||||||
$_ = $copyright ~ $_; |
|
||||||
spurt $srcp, $_; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
@ -0,0 +1,79 @@ |
|||||||
|
#!/usr/bin/env python3 |
||||||
|
|
||||||
|
# use v6; |
||||||
|
# |
||||||
|
# my $copyright = '// Copyright 2016 Zack Guo <gizak@icloud.com>. All rights reserved. |
||||||
|
# // Use of this source code is governed by a MIT license that can |
||||||
|
# // be found in the LICENSE file. |
||||||
|
# |
||||||
|
# '; |
||||||
|
# |
||||||
|
# sub MAIN('update-docstr', Str $srcp) { |
||||||
|
# if $srcp.IO.f { |
||||||
|
# $_ = $srcp.IO.slurp; |
||||||
|
# if m/^ \/\/\s Copyright .+? \n\n/ { |
||||||
|
# unless ~$/ eq $copyright { |
||||||
|
# s/^ \/\/\s Copyright .+? \n\n /$copyright/; |
||||||
|
# spurt $srcp, $_; |
||||||
|
# say "[updated] doc string for:"~$srcp; |
||||||
|
# } |
||||||
|
# } else { |
||||||
|
# say "[added] doc string for "~$srcp~" (no match found)"; |
||||||
|
# $_ = $copyright ~ $_; |
||||||
|
# spurt $srcp, $_; |
||||||
|
# } |
||||||
|
# } |
||||||
|
# } |
||||||
|
|
||||||
|
import re |
||||||
|
import os |
||||||
|
import io |
||||||
|
|
||||||
|
copyright = """// Copyright 2016 Zack Guo <zack.y.guo@gmail.com>. All rights reserved. |
||||||
|
// Use of this source code is governed by a MIT license that can |
||||||
|
// be found in the LICENSE file. |
||||||
|
|
||||||
|
""" |
||||||
|
|
||||||
|
exclude_dirs = [".git", "_docs"] |
||||||
|
exclude_files = [] |
||||||
|
include_dirs = [".", "debug", "extra", "test", "_example"] |
||||||
|
|
||||||
|
|
||||||
|
def is_target(fpath): |
||||||
|
if os.path.splitext(fpath)[-1] == ".go": |
||||||
|
return True |
||||||
|
return False |
||||||
|
|
||||||
|
|
||||||
|
def update_copyright(fpath): |
||||||
|
print("processing " + fpath) |
||||||
|
f = io.open(fpath, 'r', encoding='utf-8') |
||||||
|
fstr = f.read() |
||||||
|
f.close() |
||||||
|
|
||||||
|
# remove old |
||||||
|
m = re.search('^// Copyright .+?\r?\n\r?\n', fstr, re.MULTILINE|re.DOTALL) |
||||||
|
if m: |
||||||
|
fstr = fstr[m.end():] |
||||||
|
|
||||||
|
# add new |
||||||
|
fstr = copyright + fstr |
||||||
|
f = io.open(fpath, 'w',encoding='utf-8') |
||||||
|
f.write(fstr) |
||||||
|
f.close() |
||||||
|
|
||||||
|
|
||||||
|
def main(): |
||||||
|
for d in include_dirs: |
||||||
|
files = [ |
||||||
|
os.path.join(d, f) for f in os.listdir(d) |
||||||
|
if os.path.isfile(os.path.join(d, f)) |
||||||
|
] |
||||||
|
for f in files: |
||||||
|
if is_target(f): |
||||||
|
update_copyright(f) |
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__': |
||||||
|
main() |
@ -1,14 +1,30 @@ |
|||||||
hash: 67a478802ee1d122cf1df063c52458d074864900c96a5cc25dc6be4b7638eb1c |
hash: 7a754ba100256404a978b2fc8738aee337beb822458e4b6060399fb89ebd215c |
||||||
updated: 2016-04-06T21:16:00.849048757-04:00 |
updated: 2016-11-03T17:39:24.323773674-04:00 |
||||||
imports: |
imports: |
||||||
|
- name: github.com/maruel/panicparse |
||||||
|
version: ad661195ed0e88491e0f14be6613304e3b1141d6 |
||||||
|
subpackages: |
||||||
|
- stack |
||||||
- name: github.com/mattn/go-runewidth |
- name: github.com/mattn/go-runewidth |
||||||
version: d6bea18f789704b5f83375793155289da36a3c7f |
version: 737072b4e32b7a5018b4a7125da8d12de90e8045 |
||||||
- name: github.com/mitchellh/go-wordwrap |
- name: github.com/mitchellh/go-wordwrap |
||||||
version: ad45545899c7b13c020ea92b2072220eefad42b8 |
version: ad45545899c7b13c020ea92b2072220eefad42b8 |
||||||
- name: github.com/nsf/termbox-go |
- name: github.com/nsf/termbox-go |
||||||
version: 362329b0aa6447eadd52edd8d660ec1dff470295 |
version: b6acae516ace002cb8105a89024544a1480655a5 |
||||||
- name: golang.org/x/net |
- name: golang.org/x/net |
||||||
version: af4fee9d05b66edc24197d189e6118f8ebce8c2b |
version: 569280fa63be4e201b975e5411e30a92178f0118 |
||||||
subpackages: |
subpackages: |
||||||
- websocket |
- websocket |
||||||
devImports: [] |
testImports: |
||||||
|
- name: github.com/davecgh/go-spew |
||||||
|
version: 346938d642f2ec3594ed81d874461961cd0faa76 |
||||||
|
subpackages: |
||||||
|
- spew |
||||||
|
- name: github.com/pmezard/go-difflib |
||||||
|
version: d8ed2627bdf02c080bf22230dbb337003b7aba2d |
||||||
|
subpackages: |
||||||
|
- difflib |
||||||
|
- name: github.com/stretchr/testify |
||||||
|
version: 976c720a22c8eb4eb6a0b4348ad85ad12491a506 |
||||||
|
subpackages: |
||||||
|
- assert |
||||||
|
@ -0,0 +1,170 @@ |
|||||||
|
package termui |
||||||
|
|
||||||
|
import "strings" |
||||||
|
|
||||||
|
/* |
||||||
|
table := termui.NewTable() |
||||||
|
table.Rows = rows |
||||||
|
table.FgColor = termui.ColorWhite |
||||||
|
table.BgColor = termui.ColorDefault |
||||||
|
table.Height = 7 |
||||||
|
table.Width = 62 |
||||||
|
table.Y = 0 |
||||||
|
table.X = 0 |
||||||
|
table.Border = true |
||||||
|
*/ |
||||||
|
|
||||||
|
type Table struct { |
||||||
|
Block |
||||||
|
Rows [][]string |
||||||
|
CellWidth []int |
||||||
|
FgColor Attribute |
||||||
|
BgColor Attribute |
||||||
|
FgColors []Attribute |
||||||
|
BgColors []Attribute |
||||||
|
Seperator bool |
||||||
|
TextAlign Align |
||||||
|
} |
||||||
|
|
||||||
|
func NewTable() *Table { |
||||||
|
table := &Table{Block: *NewBlock()} |
||||||
|
table.FgColor = ColorWhite |
||||||
|
table.BgColor = ColorDefault |
||||||
|
table.Seperator = true |
||||||
|
return table |
||||||
|
} |
||||||
|
|
||||||
|
func (table *Table) Analysis() { |
||||||
|
length := len(table.Rows) |
||||||
|
if length < 1 { |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
if len(table.FgColors) == 0 { |
||||||
|
table.FgColors = make([]Attribute, len(table.Rows)) |
||||||
|
} |
||||||
|
if len(table.BgColors) == 0 { |
||||||
|
table.BgColors = make([]Attribute, len(table.Rows)) |
||||||
|
} |
||||||
|
|
||||||
|
row_width := len(table.Rows[0]) |
||||||
|
cellWidthes := make([]int, row_width) |
||||||
|
|
||||||
|
for index, row := range table.Rows { |
||||||
|
for i, str := range row { |
||||||
|
if cellWidthes[i] < len(str) { |
||||||
|
cellWidthes[i] = len(str) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if table.FgColors[index] == 0 { |
||||||
|
table.FgColors[index] = table.FgColor |
||||||
|
} |
||||||
|
|
||||||
|
if table.BgColors[index] == 0 { |
||||||
|
table.BgColors[index] = table.BgColor |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
table.CellWidth = cellWidthes |
||||||
|
|
||||||
|
//width_sum := 2
|
||||||
|
//for i, width := range cellWidthes {
|
||||||
|
// width_sum += (width + 2)
|
||||||
|
// for u, row := range table.Rows {
|
||||||
|
// switch table.TextAlign {
|
||||||
|
// case "right":
|
||||||
|
// row[i] = fmt.Sprintf(" %*s ", width, table.Rows[u][i])
|
||||||
|
// case "center":
|
||||||
|
// word_width := len(table.Rows[u][i])
|
||||||
|
// offset := (width - word_width) / 2
|
||||||
|
// row[i] = fmt.Sprintf(" %*s ", width, fmt.Sprintf("%-*s", offset+word_width, table.Rows[u][i]))
|
||||||
|
// default: // left
|
||||||
|
// row[i] = fmt.Sprintf(" %-*s ", width, table.Rows[u][i])
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
|
//if table.Width == 0 {
|
||||||
|
// table.Width = width_sum
|
||||||
|
//}
|
||||||
|
} |
||||||
|
|
||||||
|
func (table *Table) SetSize() { |
||||||
|
length := len(table.Rows) |
||||||
|
if table.Seperator { |
||||||
|
table.Height = length*2 + 1 |
||||||
|
} else { |
||||||
|
table.Height = length + 2 |
||||||
|
} |
||||||
|
table.Width = 2 |
||||||
|
if length != 0 { |
||||||
|
for _, cell_width := range table.CellWidth { |
||||||
|
table.Width += cell_width + 3 |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
func (table *Table) CalculatePosition(x int, y int, x_coordinate *int, y_coordibate *int, cell_beginning *int) { |
||||||
|
if table.Seperator { |
||||||
|
*y_coordibate = table.innerArea.Min.Y + y*2 |
||||||
|
} else { |
||||||
|
*y_coordibate = table.innerArea.Min.Y + y |
||||||
|
} |
||||||
|
if x == 0 { |
||||||
|
*cell_beginning = table.innerArea.Min.X |
||||||
|
} else { |
||||||
|
*cell_beginning += table.CellWidth[x-1] + 3 |
||||||
|
} |
||||||
|
|
||||||
|
switch table.TextAlign { |
||||||
|
case AlignRight: |
||||||
|
*x_coordinate = *cell_beginning + (table.CellWidth[x] - len(table.Rows[y][x])) + 2 |
||||||
|
case AlignCenter: |
||||||
|
*x_coordinate = *cell_beginning + (table.CellWidth[x]-len(table.Rows[y][x]))/2 + 2 |
||||||
|
default: |
||||||
|
*x_coordinate = *cell_beginning + 2 |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
func (table *Table) Buffer() Buffer { |
||||||
|
buffer := table.Block.Buffer() |
||||||
|
table.Analysis() |
||||||
|
|
||||||
|
pointer_x := table.innerArea.Min.X + 2 |
||||||
|
pointer_y := table.innerArea.Min.Y |
||||||
|
border_pointer_x := table.innerArea.Min.X |
||||||
|
for y, row := range table.Rows { |
||||||
|
for x, cell := range row { |
||||||
|
table.CalculatePosition(x, y, &pointer_x, &pointer_y, &border_pointer_x) |
||||||
|
backgraound := DefaultTxBuilder.Build(strings.Repeat(" ", table.CellWidth[x]+3), table.BgColors[y], table.BgColors[y]) |
||||||
|
cells := DefaultTxBuilder.Build(cell, table.FgColors[y], table.BgColors[y]) |
||||||
|
|
||||||
|
for i, back := range backgraound { |
||||||
|
buffer.Set(border_pointer_x+i, pointer_y, back) |
||||||
|
} |
||||||
|
|
||||||
|
coordinate_x := pointer_x |
||||||
|
for _, printer := range cells { |
||||||
|
buffer.Set(coordinate_x, pointer_y, printer) |
||||||
|
coordinate_x += printer.Width() |
||||||
|
} |
||||||
|
|
||||||
|
if x != 0 { |
||||||
|
devidors := DefaultTxBuilder.Build("|", table.FgColors[y], table.BgColors[y]) |
||||||
|
for _, devidor := range devidors { |
||||||
|
buffer.Set(border_pointer_x, pointer_y, devidor) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if table.Seperator { |
||||||
|
border := DefaultTxBuilder.Build(strings.Repeat("─", table.Width-2), table.FgColor, table.BgColor) |
||||||
|
for i, cell := range border { |
||||||
|
buffer.Set(i+1, pointer_y+1, cell) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return buffer |
||||||
|
} |
@ -0,0 +1,15 @@ |
|||||||
|
# Copyright 2014 Marc-Antoine Ruel. All rights reserved. |
||||||
|
# Use of this source code is governed under the Apache License, Version 2.0 |
||||||
|
# that can be found in the LICENSE file. |
||||||
|
|
||||||
|
sudo: false |
||||||
|
language: go |
||||||
|
|
||||||
|
go: |
||||||
|
- tip |
||||||
|
|
||||||
|
before_install: |
||||||
|
- go get github.com/maruel/pre-commit-go/cmd/pcg |
||||||
|
|
||||||
|
script: |
||||||
|
- pcg |
@ -0,0 +1,201 @@ |
|||||||
|
Apache License |
||||||
|
Version 2.0, January 2004 |
||||||
|
http://www.apache.org/licenses/ |
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION |
||||||
|
|
||||||
|
1. Definitions. |
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction, |
||||||
|
and distribution as defined by Sections 1 through 9 of this document. |
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by |
||||||
|
the copyright owner that is granting the License. |
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all |
||||||
|
other entities that control, are controlled by, or are under common |
||||||
|
control with that entity. For the purposes of this definition, |
||||||
|
"control" means (i) the power, direct or indirect, to cause the |
||||||
|
direction or management of such entity, whether by contract or |
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the |
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity. |
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity |
||||||
|
exercising permissions granted by this License. |
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications, |
||||||
|
including but not limited to software source code, documentation |
||||||
|
source, and configuration files. |
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical |
||||||
|
transformation or translation of a Source form, including but |
||||||
|
not limited to compiled object code, generated documentation, |
||||||
|
and conversions to other media types. |
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or |
||||||
|
Object form, made available under the License, as indicated by a |
||||||
|
copyright notice that is included in or attached to the work |
||||||
|
(an example is provided in the Appendix below). |
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object |
||||||
|
form, that is based on (or derived from) the Work and for which the |
||||||
|
editorial revisions, annotations, elaborations, or other modifications |
||||||
|
represent, as a whole, an original work of authorship. For the purposes |
||||||
|
of this License, Derivative Works shall not include works that remain |
||||||
|
separable from, or merely link (or bind by name) to the interfaces of, |
||||||
|
the Work and Derivative Works thereof. |
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including |
||||||
|
the original version of the Work and any modifications or additions |
||||||
|
to that Work or Derivative Works thereof, that is intentionally |
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner |
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of |
||||||
|
the copyright owner. For the purposes of this definition, "submitted" |
||||||
|
means any form of electronic, verbal, or written communication sent |
||||||
|
to the Licensor or its representatives, including but not limited to |
||||||
|
communication on electronic mailing lists, source code control systems, |
||||||
|
and issue tracking systems that are managed by, or on behalf of, the |
||||||
|
Licensor for the purpose of discussing and improving the Work, but |
||||||
|
excluding communication that is conspicuously marked or otherwise |
||||||
|
designated in writing by the copyright owner as "Not a Contribution." |
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity |
||||||
|
on behalf of whom a Contribution has been received by Licensor and |
||||||
|
subsequently incorporated within the Work. |
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of |
||||||
|
this License, each Contributor hereby grants to You a perpetual, |
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable |
||||||
|
copyright license to reproduce, prepare Derivative Works of, |
||||||
|
publicly display, publicly perform, sublicense, and distribute the |
||||||
|
Work and such Derivative Works in Source or Object form. |
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of |
||||||
|
this License, each Contributor hereby grants to You a perpetual, |
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable |
||||||
|
(except as stated in this section) patent license to make, have made, |
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work, |
||||||
|
where such license applies only to those patent claims licensable |
||||||
|
by such Contributor that are necessarily infringed by their |
||||||
|
Contribution(s) alone or by combination of their Contribution(s) |
||||||
|
with the Work to which such Contribution(s) was submitted. If You |
||||||
|
institute patent litigation against any entity (including a |
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work |
||||||
|
or a Contribution incorporated within the Work constitutes direct |
||||||
|
or contributory patent infringement, then any patent licenses |
||||||
|
granted to You under this License for that Work shall terminate |
||||||
|
as of the date such litigation is filed. |
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the |
||||||
|
Work or Derivative Works thereof in any medium, with or without |
||||||
|
modifications, and in Source or Object form, provided that You |
||||||
|
meet the following conditions: |
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or |
||||||
|
Derivative Works a copy of this License; and |
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices |
||||||
|
stating that You changed the files; and |
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works |
||||||
|
that You distribute, all copyright, patent, trademark, and |
||||||
|
attribution notices from the Source form of the Work, |
||||||
|
excluding those notices that do not pertain to any part of |
||||||
|
the Derivative Works; and |
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its |
||||||
|
distribution, then any Derivative Works that You distribute must |
||||||
|
include a readable copy of the attribution notices contained |
||||||
|
within such NOTICE file, excluding those notices that do not |
||||||
|
pertain to any part of the Derivative Works, in at least one |
||||||
|
of the following places: within a NOTICE text file distributed |
||||||
|
as part of the Derivative Works; within the Source form or |
||||||
|
documentation, if provided along with the Derivative Works; or, |
||||||
|
within a display generated by the Derivative Works, if and |
||||||
|
wherever such third-party notices normally appear. The contents |
||||||
|
of the NOTICE file are for informational purposes only and |
||||||
|
do not modify the License. You may add Your own attribution |
||||||
|
notices within Derivative Works that You distribute, alongside |
||||||
|
or as an addendum to the NOTICE text from the Work, provided |
||||||
|
that such additional attribution notices cannot be construed |
||||||
|
as modifying the License. |
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and |
||||||
|
may provide additional or different license terms and conditions |
||||||
|
for use, reproduction, or distribution of Your modifications, or |
||||||
|
for any such Derivative Works as a whole, provided Your use, |
||||||
|
reproduction, and distribution of the Work otherwise complies with |
||||||
|
the conditions stated in this License. |
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise, |
||||||
|
any Contribution intentionally submitted for inclusion in the Work |
||||||
|
by You to the Licensor shall be under the terms and conditions of |
||||||
|
this License, without any additional terms or conditions. |
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify |
||||||
|
the terms of any separate license agreement you may have executed |
||||||
|
with Licensor regarding such Contributions. |
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade |
||||||
|
names, trademarks, service marks, or product names of the Licensor, |
||||||
|
except as required for reasonable and customary use in describing the |
||||||
|
origin of the Work and reproducing the content of the NOTICE file. |
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or |
||||||
|
agreed to in writing, Licensor provides the Work (and each |
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS, |
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or |
||||||
|
implied, including, without limitation, any warranties or conditions |
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A |
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the |
||||||
|
appropriateness of using or redistributing the Work and assume any |
||||||
|
risks associated with Your exercise of permissions under this License. |
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory, |
||||||
|
whether in tort (including negligence), contract, or otherwise, |
||||||
|
unless required by applicable law (such as deliberate and grossly |
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be |
||||||
|
liable to You for damages, including any direct, indirect, special, |
||||||
|
incidental, or consequential damages of any character arising as a |
||||||
|
result of this License or out of the use or inability to use the |
||||||
|
Work (including but not limited to damages for loss of goodwill, |
||||||
|
work stoppage, computer failure or malfunction, or any and all |
||||||
|
other commercial damages or losses), even if such Contributor |
||||||
|
has been advised of the possibility of such damages. |
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing |
||||||
|
the Work or Derivative Works thereof, You may choose to offer, |
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity, |
||||||
|
or other liability obligations and/or rights consistent with this |
||||||
|
License. However, in accepting such obligations, You may act only |
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf |
||||||
|
of any other Contributor, and only if You agree to indemnify, |
||||||
|
defend, and hold each Contributor harmless for any liability |
||||||
|
incurred by, or claims asserted against, such Contributor by reason |
||||||
|
of your accepting any such warranty or additional liability. |
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS |
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work. |
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following |
||||||
|
boilerplate notice, with the fields enclosed by brackets "{}" |
||||||
|
replaced with your own identifying information. (Don't include |
||||||
|
the brackets!) The text should be enclosed in the appropriate |
||||||
|
comment syntax for the file format. We also recommend that a |
||||||
|
file or class name and description of purpose be included on the |
||||||
|
same "printed page" as the copyright notice for easier |
||||||
|
identification within third-party archives. |
||||||
|
|
||||||
|
Copyright 2015 Marc-Antoine Ruel |
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
you may not use this file except in compliance with the License. |
||||||
|
You may obtain a copy of the License at |
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software |
||||||
|
distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
See the License for the specific language governing permissions and |
||||||
|
limitations under the License. |
@ -0,0 +1,123 @@ |
|||||||
|
panicparse |
||||||
|
========== |
||||||
|
|
||||||
|
Parses panic stack traces, densifies and deduplicates goroutines with similar |
||||||
|
stack traces. Helps debugging crashes and deadlocks in heavily parallelized |
||||||
|
process. |
||||||
|
|
||||||
|
[![Build Status](https://travis-ci.org/maruel/panicparse.svg?branch=master)](https://travis-ci.org/maruel/panicparse) |
||||||
|
|
||||||
|
panicparse helps make sense of Go crash dumps: |
||||||
|
|
||||||
|
![Screencast](https://raw.githubusercontent.com/wiki/maruel/panicparse/parse.gif "Screencast") |
||||||
|
|
||||||
|
|
||||||
|
Features |
||||||
|
-------- |
||||||
|
|
||||||
|
* >50% more compact output than original stack dump yet more readable. |
||||||
|
* Exported symbols are bold, private symbols are darker. |
||||||
|
* Stdlib is green, main is yellow, rest is red. |
||||||
|
* Deduplicates redundant goroutine stacks. Useful for large server crashes. |
||||||
|
* Arguments as pointer IDs instead of raw pointer values. |
||||||
|
* Pushes stdlib-only stacks at the bottom to help focus on important code. |
||||||
|
* Usable as a library! |
||||||
|
[![GoDoc](https://godoc.org/github.com/maruel/panicparse/stack?status.svg)](https://godoc.org/github.com/maruel/panicparse/stack) |
||||||
|
* Warning: please pin the version (e.g. vendor it). Breaking changes are |
||||||
|
not planned but may happen. |
||||||
|
* Parses the source files if available to augment the output. |
||||||
|
* Works on Windows. |
||||||
|
|
||||||
|
|
||||||
|
Installation |
||||||
|
------------ |
||||||
|
|
||||||
|
go get github.com/maruel/panicparse/cmd/pp |
||||||
|
|
||||||
|
|
||||||
|
Usage |
||||||
|
----- |
||||||
|
|
||||||
|
### Piping a stack trace from another process |
||||||
|
|
||||||
|
#### TL;DR |
||||||
|
|
||||||
|
* Ubuntu (bash v4 or zsh): `|&` |
||||||
|
* OSX, [install bash 4+](README.md#updating-bash-on-osx), then: `|&` |
||||||
|
* Windows _or_ OSX with stock bash v3: `2>&1 |` |
||||||
|
* [Fish](http://fishshell.com/) shell: `^|` |
||||||
|
|
||||||
|
|
||||||
|
#### Longer version |
||||||
|
|
||||||
|
`pp` streams its stdin to stdout as long as it doesn't detect any panic. |
||||||
|
`panic()` and Go's native deadlock detector [print to |
||||||
|
stderr](https://golang.org/src/runtime/panic1.go) via the native [`print()` |
||||||
|
function](https://golang.org/pkg/builtin/#print). |
||||||
|
|
||||||
|
|
||||||
|
**Bash v4** or **zsh**: `|&` tells the shell to redirect stderr to stdout, |
||||||
|
it's an alias for `2>&1 |` ([bash |
||||||
|
v4](https://www.gnu.org/software/bash/manual/bash.html#Pipelines), |
||||||
|
[zsh](http://zsh.sourceforge.net/Doc/Release/Shell-Grammar.html#Simple-Commands-_0026-Pipelines)): |
||||||
|
|
||||||
|
go test -v |&pp |
||||||
|
|
||||||
|
|
||||||
|
**Windows or OSX native bash** [(which is |
||||||
|
3.2.57)](http://meta.ath0.com/2012/02/05/apples-great-gpl-purge/): They don't |
||||||
|
have this shortcut, so use the long form: |
||||||
|
|
||||||
|
go test -v 2>&1 | pp |
||||||
|
|
||||||
|
|
||||||
|
**Fish**: It uses [^ for stderr |
||||||
|
redirection](http://fishshell.com/docs/current/tutorial.html#tut_pipes_and_redirections) |
||||||
|
so the shortcut is `^|`: |
||||||
|
|
||||||
|
go test -v ^|pp |
||||||
|
|
||||||
|
|
||||||
|
**PowerShell**: [It has broken `2>&1` redirection](https://connect.microsoft.com/PowerShell/feedback/details/765551/in-powershell-v3-you-cant-redirect-stderr-to-stdout-without-generating-error-records). The workaround is to shell out to cmd.exe. :( |
||||||
|
|
||||||
|
|
||||||
|
### Investigate deadlock |
||||||
|
|
||||||
|
On POSIX, use `Ctrl-\` to send SIGQUIT to your process, `pp` will ignore |
||||||
|
the signal and will parse the stack trace. |
||||||
|
|
||||||
|
|
||||||
|
### Parsing from a file |
||||||
|
|
||||||
|
To dump to a file then parse, pass the file path of a stack trace |
||||||
|
|
||||||
|
go test 2> stack.txt |
||||||
|
pp stack.txt |
||||||
|
|
||||||
|
|
||||||
|
Tips |
||||||
|
---- |
||||||
|
|
||||||
|
### GOTRACEBACK |
||||||
|
|
||||||
|
Starting with Go 1.6, [`GOTRACEBACK`](https://golang.org/pkg/runtime/) defaults |
||||||
|
to `single` instead of `all` / `1` that was used in 1.5 and before. To get all |
||||||
|
goroutines trace and not just the crashing one, set the environment variable: |
||||||
|
|
||||||
|
export GOTRACEBACK=all |
||||||
|
|
||||||
|
or `set GOTRACEBACK=all` on Windows. Probably worth to put it in your `.bashrc`. |
||||||
|
|
||||||
|
|
||||||
|
### Updating bash on OSX |
||||||
|
|
||||||
|
Install bash v4+ on OSX via [homebrew](http://brew.sh) or |
||||||
|
[macports](https://www.macports.org/). Your future self will appreciate having |
||||||
|
done that. |
||||||
|
|
||||||
|
|
||||||
|
### If you have `/usr/bin/pp` installed |
||||||
|
|
||||||
|
You may have the Perl PAR Packager installed. Use long name `panicparse` then; |
||||||
|
|
||||||
|
go get github.com/maruel/panicparse |
@ -0,0 +1,291 @@ |
|||||||
|
// Copyright 2015 Marc-Antoine Ruel. All rights reserved.
|
||||||
|
// Use of this source code is governed under the Apache License, Version 2.0
|
||||||
|
// that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// This file contains the code to process sources, to be able to deduct the
|
||||||
|
// original types.
|
||||||
|
|
||||||
|
package stack |
||||||
|
|
||||||
|
import ( |
||||||
|
"bytes" |
||||||
|
"fmt" |
||||||
|
"go/ast" |
||||||
|
"go/parser" |
||||||
|
"go/token" |
||||||
|
"io/ioutil" |
||||||
|
"log" |
||||||
|
"math" |
||||||
|
"strings" |
||||||
|
) |
||||||
|
|
||||||
|
// cache is a cache of sources on the file system.
|
||||||
|
type cache struct { |
||||||
|
files map[string][]byte |
||||||
|
parsed map[string]*parsedFile |
||||||
|
} |
||||||
|
|
||||||
|
// Augment processes source files to improve calls to be more descriptive.
|
||||||
|
//
|
||||||
|
// It modifies goroutines in place.
|
||||||
|
func Augment(goroutines []Goroutine) { |
||||||
|
c := &cache{} |
||||||
|
for i := range goroutines { |
||||||
|
c.augmentGoroutine(&goroutines[i]) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// augmentGoroutine processes source files to improve call to be more
|
||||||
|
// descriptive.
|
||||||
|
//
|
||||||
|
// It modifies the routine.
|
||||||
|
func (c *cache) augmentGoroutine(goroutine *Goroutine) { |
||||||
|
if c.files == nil { |
||||||
|
c.files = map[string][]byte{} |
||||||
|
} |
||||||
|
if c.parsed == nil { |
||||||
|
c.parsed = map[string]*parsedFile{} |
||||||
|
} |
||||||
|
// For each call site, look at the next call and populate it. Then we can
|
||||||
|
// walk back and reformat things.
|
||||||
|
for i := range goroutine.Stack.Calls { |
||||||
|
c.load(goroutine.Stack.Calls[i].SourcePath) |
||||||
|
} |
||||||
|
|
||||||
|
// Once all loaded, we can look at the next call when available.
|
||||||
|
for i := 1; i < len(goroutine.Stack.Calls); i++ { |
||||||
|
// Get the AST from the previous call and process the call line with it.
|
||||||
|
if f := c.getFuncAST(&goroutine.Stack.Calls[i]); f != nil { |
||||||
|
processCall(&goroutine.Stack.Calls[i], f) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Private stuff.
|
||||||
|
|
||||||
|
// load loads a source file and parses the AST tree. Failures are ignored.
|
||||||
|
func (c *cache) load(fileName string) { |
||||||
|
if _, ok := c.parsed[fileName]; ok { |
||||||
|
return |
||||||
|
} |
||||||
|
c.parsed[fileName] = nil |
||||||
|
if !strings.HasSuffix(fileName, ".go") { |
||||||
|
// Ignore C and assembly.
|
||||||
|
c.files[fileName] = nil |
||||||
|
return |
||||||
|
} |
||||||
|
log.Printf("load(%s)", fileName) |
||||||
|
if _, ok := c.files[fileName]; !ok { |
||||||
|
var err error |
||||||
|
if c.files[fileName], err = ioutil.ReadFile(fileName); err != nil { |
||||||
|
log.Printf("Failed to read %s: %s", fileName, err) |
||||||
|
c.files[fileName] = nil |
||||||
|
return |
||||||
|
} |
||||||
|
} |
||||||
|
fset := token.NewFileSet() |
||||||
|
src := c.files[fileName] |
||||||
|
parsed, err := parser.ParseFile(fset, fileName, src, 0) |
||||||
|
if err != nil { |
||||||
|
log.Printf("Failed to parse %s: %s", fileName, err) |
||||||
|
return |
||||||
|
} |
||||||
|
// Convert the line number into raw file offset.
|
||||||
|
offsets := []int{0, 0} |
||||||
|
start := 0 |
||||||
|
for l := 1; start < len(src); l++ { |
||||||
|
start += bytes.IndexByte(src[start:], '\n') + 1 |
||||||
|
offsets = append(offsets, start) |
||||||
|
} |
||||||
|
c.parsed[fileName] = &parsedFile{offsets, parsed} |
||||||
|
} |
||||||
|
|
||||||
|
func (c *cache) getFuncAST(call *Call) *ast.FuncDecl { |
||||||
|
if p := c.parsed[call.SourcePath]; p != nil { |
||||||
|
return p.getFuncAST(call.Func.Name(), call.Line) |
||||||
|
} |
||||||
|
return nil |
||||||
|
} |
||||||
|
|
||||||
|
type parsedFile struct { |
||||||
|
lineToByteOffset []int |
||||||
|
parsed *ast.File |
||||||
|
} |
||||||
|
|
||||||
|
// getFuncAST gets the callee site function AST representation for the code
|
||||||
|
// inside the function f at line l.
|
||||||
|
func (p *parsedFile) getFuncAST(f string, l int) (d *ast.FuncDecl) { |
||||||
|
// Walk the AST to find the lineToByteOffset that fits the line number.
|
||||||
|
var lastFunc *ast.FuncDecl |
||||||
|
var found ast.Node |
||||||
|
// Inspect() goes depth first. This means for example that a function like:
|
||||||
|
// func a() {
|
||||||
|
// b := func() {}
|
||||||
|
// c()
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Were we are looking at the c() call can return confused values. It is
|
||||||
|
// important to look at the actual ast.Node hierarchy.
|
||||||
|
ast.Inspect(p.parsed, func(n ast.Node) bool { |
||||||
|
if d != nil { |
||||||
|
return false |
||||||
|
} |
||||||
|
if n == nil { |
||||||
|
return true |
||||||
|
} |
||||||
|
if found != nil { |
||||||
|
// We are walking up.
|
||||||
|
} |
||||||
|
if int(n.Pos()) >= p.lineToByteOffset[l] { |
||||||
|
// We are expecting a ast.CallExpr node. It can be harder to figure out
|
||||||
|
// when there are multiple calls on a single line, as the stack trace
|
||||||
|
// doesn't have file byte offset information, only line based.
|
||||||
|
// gofmt will always format to one function call per line but there can
|
||||||
|
// be edge cases, like:
|
||||||
|
// a = A{Foo(), Bar()}
|
||||||
|
d = lastFunc |
||||||
|
//p.processNode(call, n)
|
||||||
|
return false |
||||||
|
} else if f, ok := n.(*ast.FuncDecl); ok { |
||||||
|
lastFunc = f |
||||||
|
} |
||||||
|
return true |
||||||
|
}) |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
func name(n ast.Node) string { |
||||||
|
if _, ok := n.(*ast.InterfaceType); ok { |
||||||
|
return "interface{}" |
||||||
|
} |
||||||
|
if i, ok := n.(*ast.Ident); ok { |
||||||
|
return i.Name |
||||||
|
} |
||||||
|
if _, ok := n.(*ast.FuncType); ok { |
||||||
|
return "func" |
||||||
|
} |
||||||
|
if s, ok := n.(*ast.SelectorExpr); ok { |
||||||
|
return s.Sel.Name |
||||||
|
} |
||||||
|
// TODO(maruel): Implement anything missing.
|
||||||
|
return "<unknown>" |
||||||
|
} |
||||||
|
|
||||||
|
// fieldToType returns the type name and whether if it's an ellipsis.
|
||||||
|
func fieldToType(f *ast.Field) (string, bool) { |
||||||
|
switch arg := f.Type.(type) { |
||||||
|
case *ast.ArrayType: |
||||||
|
return "[]" + name(arg.Elt), false |
||||||
|
case *ast.Ellipsis: |
||||||
|
return name(arg.Elt), true |
||||||
|
case *ast.FuncType: |
||||||
|
// Do not print the function signature to not overload the trace.
|
||||||
|
return "func", false |
||||||
|
case *ast.Ident: |
||||||
|
return arg.Name, false |
||||||
|
case *ast.InterfaceType: |
||||||
|
return "interface{}", false |
||||||
|
case *ast.SelectorExpr: |
||||||
|
return arg.Sel.Name, false |
||||||
|
case *ast.StarExpr: |
||||||
|
return "*" + name(arg.X), false |
||||||
|
default: |
||||||
|
// TODO(maruel): Implement anything missing.
|
||||||
|
return "<unknown>", false |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// extractArgumentsType returns the name of the type of each input argument.
|
||||||
|
func extractArgumentsType(f *ast.FuncDecl) ([]string, bool) { |
||||||
|
var fields []*ast.Field |
||||||
|
if f.Recv != nil { |
||||||
|
if len(f.Recv.List) != 1 { |
||||||
|
panic("Expect only one receiver; please fix panicparse's code") |
||||||
|
} |
||||||
|
// If it is an object receiver (vs a pointer receiver), its address is not
|
||||||
|
// printed in the stack trace so it needs to be ignored.
|
||||||
|
if _, ok := f.Recv.List[0].Type.(*ast.StarExpr); ok { |
||||||
|
fields = append(fields, f.Recv.List[0]) |
||||||
|
} |
||||||
|
} |
||||||
|
var types []string |
||||||
|
extra := false |
||||||
|
for _, arg := range append(fields, f.Type.Params.List...) { |
||||||
|
// Assert that extra is only set on the last item of fields?
|
||||||
|
var t string |
||||||
|
t, extra = fieldToType(arg) |
||||||
|
mult := len(arg.Names) |
||||||
|
if mult == 0 { |
||||||
|
mult = 1 |
||||||
|
} |
||||||
|
for i := 0; i < mult; i++ { |
||||||
|
types = append(types, t) |
||||||
|
} |
||||||
|
} |
||||||
|
return types, extra |
||||||
|
} |
||||||
|
|
||||||
|
// processCall walks the function and populate call accordingly.
|
||||||
|
func processCall(call *Call, f *ast.FuncDecl) { |
||||||
|
values := make([]uint64, len(call.Args.Values)) |
||||||
|
for i := range call.Args.Values { |
||||||
|
values[i] = call.Args.Values[i].Value |
||||||
|
} |
||||||
|
index := 0 |
||||||
|
pop := func() uint64 { |
||||||
|
if len(values) != 0 { |
||||||
|
x := values[0] |
||||||
|
values = values[1:] |
||||||
|
index++ |
||||||
|
return x |
||||||
|
} |
||||||
|
return 0 |
||||||
|
} |
||||||
|
popName := func() string { |
||||||
|
n := call.Args.Values[index].Name |
||||||
|
v := pop() |
||||||
|
if len(n) == 0 { |
||||||
|
return fmt.Sprintf("0x%x", v) |
||||||
|
} |
||||||
|
return n |
||||||
|
} |
||||||
|
|
||||||
|
types, extra := extractArgumentsType(f) |
||||||
|
for i := 0; len(values) != 0; i++ { |
||||||
|
var t string |
||||||
|
if i >= len(types) { |
||||||
|
if !extra { |
||||||
|
// These are unexpected value! Print them as hex.
|
||||||
|
call.Args.Processed = append(call.Args.Processed, popName()) |
||||||
|
continue |
||||||
|
} |
||||||
|
t = types[len(types)-1] |
||||||
|
} else { |
||||||
|
t = types[i] |
||||||
|
} |
||||||
|
switch t { |
||||||
|
case "float32": |
||||||
|
call.Args.Processed = append(call.Args.Processed, fmt.Sprintf("%g", math.Float32frombits(uint32(pop())))) |
||||||
|
case "float64": |
||||||
|
call.Args.Processed = append(call.Args.Processed, fmt.Sprintf("%g", math.Float64frombits(pop()))) |
||||||
|
case "int", "int8", "int16", "int32", "int64", "uint", "uint8", "uint16", "uint32", "uint64": |
||||||
|
call.Args.Processed = append(call.Args.Processed, fmt.Sprintf("%d", pop())) |
||||||
|
case "string": |
||||||
|
call.Args.Processed = append(call.Args.Processed, fmt.Sprintf("%s(%s, len=%d)", t, popName(), pop())) |
||||||
|
default: |
||||||
|
if strings.HasPrefix(t, "*") { |
||||||
|
call.Args.Processed = append(call.Args.Processed, fmt.Sprintf("%s(%s)", t, popName())) |
||||||
|
} else if strings.HasPrefix(t, "[]") { |
||||||
|
call.Args.Processed = append(call.Args.Processed, fmt.Sprintf("%s(%s len=%d cap=%d)", t, popName(), pop(), pop())) |
||||||
|
} else { |
||||||
|
// Assumes it's an interface. For now, discard the object value, which
|
||||||
|
// is probably not a good idea.
|
||||||
|
call.Args.Processed = append(call.Args.Processed, fmt.Sprintf("%s(%s)", t, popName())) |
||||||
|
pop() |
||||||
|
} |
||||||
|
} |
||||||
|
if len(values) == 0 && call.Args.Elided { |
||||||
|
return |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,832 @@ |
|||||||
|
// Copyright 2015 Marc-Antoine Ruel. All rights reserved.
|
||||||
|
// Use of this source code is governed under the Apache License, Version 2.0
|
||||||
|
// that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package stack analyzes stack dump of Go processes and simplifies it.
|
||||||
|
//
|
||||||
|
// It is mostly useful on servers will large number of identical goroutines,
|
||||||
|
// making the crash dump harder to read than strictly necesary.
|
||||||
|
package stack |
||||||
|
|
||||||
|
import ( |
||||||
|
"bufio" |
||||||
|
"bytes" |
||||||
|
"errors" |
||||||
|
"fmt" |
||||||
|
"io" |
||||||
|
"math" |
||||||
|
"net/url" |
||||||
|
"os" |
||||||
|
"path/filepath" |
||||||
|
"regexp" |
||||||
|
"runtime" |
||||||
|
"sort" |
||||||
|
"strconv" |
||||||
|
"strings" |
||||||
|
"unicode" |
||||||
|
"unicode/utf8" |
||||||
|
) |
||||||
|
|
||||||
|
const lockedToThread = "locked to thread" |
||||||
|
|
||||||
|
var ( |
||||||
|
// TODO(maruel): Handle corrupted stack cases:
|
||||||
|
// - missed stack barrier
|
||||||
|
// - found next stack barrier at 0x123; expected
|
||||||
|
// - runtime: unexpected return pc for FUNC_NAME called from 0x123
|
||||||
|
|
||||||
|
reRoutineHeader = regexp.MustCompile("^goroutine (\\d+) \\[([^\\]]+)\\]\\:\n$") |
||||||
|
reMinutes = regexp.MustCompile("^(\\d+) minutes$") |
||||||
|
reUnavail = regexp.MustCompile("^(?:\t| +)goroutine running on other thread; stack unavailable") |
||||||
|
// See gentraceback() in src/runtime/traceback.go for more information.
|
||||||
|
// - Sometimes the source file comes up as "<autogenerated>". It is the
|
||||||
|
// compiler than generated these, not the runtime.
|
||||||
|
// - The tab may be replaced with spaces when a user copy-paste it, handle
|
||||||
|
// this transparently.
|
||||||
|
// - "runtime.gopanic" is explicitly replaced with "panic" by gentraceback().
|
||||||
|
// - The +0x123 byte offset is printed when frame.pc > _func.entry. _func is
|
||||||
|
// generated by the linker.
|
||||||
|
// - The +0x123 byte offset is not included with generated code, e.g. unnamed
|
||||||
|
// functions "func·006()" which is generally go func() { ... }()
|
||||||
|
// statements. Since the _func is generated at runtime, it's probably why
|
||||||
|
// _func.entry is not set.
|
||||||
|
// - C calls may have fp=0x123 sp=0x123 appended. I think it normally happens
|
||||||
|
// when a signal is not correctly handled. It is printed with m.throwing>0.
|
||||||
|
// These are discarded.
|
||||||
|
// - For cgo, the source file may be "??".
|
||||||
|
reFile = regexp.MustCompile("^(?:\t| +)(\\?\\?|\\<autogenerated\\>|.+\\.(?:c|go|s))\\:(\\d+)(?:| \\+0x[0-9a-f]+)(?:| fp=0x[0-9a-f]+ sp=0x[0-9a-f]+)\n$") |
||||||
|
// Sadly, it doesn't note the goroutine number so we could cascade them per
|
||||||
|
// parenthood.
|
||||||
|
reCreated = regexp.MustCompile("^created by (.+)\n$") |
||||||
|
reFunc = regexp.MustCompile("^(.+)\\((.*)\\)\n$") |
||||||
|
reElided = regexp.MustCompile("^\\.\\.\\.additional frames elided\\.\\.\\.\n$") |
||||||
|
// Include frequent GOROOT value on Windows, distro provided and user
|
||||||
|
// installed path. This simplifies the user's life when processing a trace
|
||||||
|
// generated on another VM.
|
||||||
|
// TODO(maruel): Guess the path automatically via traces containing the
|
||||||
|
// 'runtime' package, which is very frequent. This would be "less bad" than
|
||||||
|
// throwing up random values at the parser.
|
||||||
|
goroots = []string{runtime.GOROOT(), "c:/go", "/usr/lib/go", "/usr/local/go"} |
||||||
|
) |
||||||
|
|
||||||
|
// Similarity is the level at which two call lines arguments must match to be
|
||||||
|
// considered similar enough to coalesce them.
|
||||||
|
type Similarity int |
||||||
|
|
||||||
|
const ( |
||||||
|
// ExactFlags requires same bits (e.g. Locked).
|
||||||
|
ExactFlags Similarity = iota |
||||||
|
// ExactLines requests the exact same arguments on the call line.
|
||||||
|
ExactLines |
||||||
|
// AnyPointer considers different pointers a similar call line.
|
||||||
|
AnyPointer |
||||||
|
// AnyValue accepts any value as similar call line.
|
||||||
|
AnyValue |
||||||
|
) |
||||||
|
|
||||||
|
// Function is a function call.
|
||||||
|
//
|
||||||
|
// Go stack traces print a mangled function call, this wrapper unmangle the
|
||||||
|
// string before printing and adds other filtering methods.
|
||||||
|
type Function struct { |
||||||
|
Raw string |
||||||
|
} |
||||||
|
|
||||||
|
// String is the fully qualified function name.
|
||||||
|
//
|
||||||
|
// Sadly Go is a bit confused when the package name doesn't match the directory
|
||||||
|
// containing the source file and will use the directory name instead of the
|
||||||
|
// real package name.
|
||||||
|
func (f Function) String() string { |
||||||
|
s, _ := url.QueryUnescape(f.Raw) |
||||||
|
return s |
||||||
|
} |
||||||
|
|
||||||
|
// Name is the naked function name.
|
||||||
|
func (f Function) Name() string { |
||||||
|
parts := strings.SplitN(filepath.Base(f.Raw), ".", 2) |
||||||
|
if len(parts) == 1 { |
||||||
|
return parts[0] |
||||||
|
} |
||||||
|
return parts[1] |
||||||
|
} |
||||||
|
|
||||||
|
// PkgName is the package name for this function reference.
|
||||||
|
func (f Function) PkgName() string { |
||||||
|
parts := strings.SplitN(filepath.Base(f.Raw), ".", 2) |
||||||
|
if len(parts) == 1 { |
||||||
|
return "" |
||||||
|
} |
||||||
|
s, _ := url.QueryUnescape(parts[0]) |
||||||
|
return s |
||||||
|
} |
||||||
|
|
||||||
|
// PkgDotName returns "<package>.<func>" format.
|
||||||
|
func (f Function) PkgDotName() string { |
||||||
|
parts := strings.SplitN(filepath.Base(f.Raw), ".", 2) |
||||||
|
s, _ := url.QueryUnescape(parts[0]) |
||||||
|
if len(parts) == 1 { |
||||||
|
return parts[0] |
||||||
|
} |
||||||
|
if s != "" || parts[1] != "" { |
||||||
|
return s + "." + parts[1] |
||||||
|
} |
||||||
|
return "" |
||||||
|
} |
||||||
|
|
||||||
|
// IsExported returns true if the function is exported.
|
||||||
|
func (f Function) IsExported() bool { |
||||||
|
name := f.Name() |
||||||
|
parts := strings.Split(name, ".") |
||||||
|
r, _ := utf8.DecodeRuneInString(parts[len(parts)-1]) |
||||||
|
if unicode.ToUpper(r) == r { |
||||||
|
return true |
||||||
|
} |
||||||
|
return f.PkgName() == "main" && name == "main" |
||||||
|
} |
||||||
|
|
||||||
|
// Arg is an argument on a Call.
|
||||||
|
type Arg struct { |
||||||
|
Value uint64 // Value is the raw value as found in the stack trace
|
||||||
|
Name string // Name is a pseudo name given to the argument
|
||||||
|
} |
||||||
|
|
||||||
|
// IsPtr returns true if we guess it's a pointer. It's only a guess, it can be
|
||||||
|
// easily be confused by a bitmask.
|
||||||
|
func (a *Arg) IsPtr() bool { |
||||||
|
// Assumes all pointers are above 16Mb and positive.
|
||||||
|
return a.Value > 16*1024*1024 && a.Value < math.MaxInt64 |
||||||
|
} |
||||||
|
|
||||||
|
func (a Arg) String() string { |
||||||
|
if a.Name != "" { |
||||||
|
return a.Name |
||||||
|
} |
||||||
|
if a.Value == 0 { |
||||||
|
return "0" |
||||||
|
} |
||||||
|
return fmt.Sprintf("0x%x", a.Value) |
||||||
|
} |
||||||
|
|
||||||
|
// Args is a series of function call arguments.
|
||||||
|
type Args struct { |
||||||
|
Values []Arg // Values is the arguments as shown on the stack trace. They are mangled via simplification.
|
||||||
|
Processed []string // Processed is the arguments generated from processing the source files. It can have a length lower than Values.
|
||||||
|
Elided bool // If set, it means there was a trailing ", ..."
|
||||||
|
} |
||||||
|
|
||||||
|
func (a Args) String() string { |
||||||
|
var v []string |
||||||
|
if len(a.Processed) != 0 { |
||||||
|
v = make([]string, 0, len(a.Processed)) |
||||||
|
for _, item := range a.Processed { |
||||||
|
v = append(v, item) |
||||||
|
} |
||||||
|
} else { |
||||||
|
v = make([]string, 0, len(a.Values)) |
||||||
|
for _, item := range a.Values { |
||||||
|
v = append(v, item.String()) |
||||||
|
} |
||||||
|
} |
||||||
|
if a.Elided { |
||||||
|
v = append(v, "...") |
||||||
|
} |
||||||
|
return strings.Join(v, ", ") |
||||||
|
} |
||||||
|
|
||||||
|
// Equal returns true only if both arguments are exactly equal.
|
||||||
|
func (a *Args) Equal(r *Args) bool { |
||||||
|
if a.Elided != r.Elided || len(a.Values) != len(r.Values) { |
||||||
|
return false |
||||||
|
} |
||||||
|
for i, l := range a.Values { |
||||||
|
if l != r.Values[i] { |
||||||
|
return false |
||||||
|
} |
||||||
|
} |
||||||
|
return true |
||||||
|
} |
||||||
|
|
||||||
|
// Similar returns true if the two Args are equal or almost but not quite
|
||||||
|
// equal.
|
||||||
|
func (a *Args) Similar(r *Args, similar Similarity) bool { |
||||||
|
if a.Elided != r.Elided || len(a.Values) != len(r.Values) { |
||||||
|
return false |
||||||
|
} |
||||||
|
if similar == AnyValue { |
||||||
|
return true |
||||||
|
} |
||||||
|
for i, l := range a.Values { |
||||||
|
switch similar { |
||||||
|
case ExactFlags, ExactLines: |
||||||
|
if l != r.Values[i] { |
||||||
|
return false |
||||||
|
} |
||||||
|
default: |
||||||
|
if l.IsPtr() != r.Values[i].IsPtr() || (!l.IsPtr() && l != r.Values[i]) { |
||||||
|
return false |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return true |
||||||
|
} |
||||||
|
|
||||||
|
// Merge merges two similar Args, zapping out differences.
|
||||||
|
func (a *Args) Merge(r *Args) Args { |
||||||
|
out := Args{ |
||||||
|
Values: make([]Arg, len(a.Values)), |
||||||
|
Elided: a.Elided, |
||||||
|
} |
||||||
|
for i, l := range a.Values { |
||||||
|
if l != r.Values[i] { |
||||||
|
out.Values[i].Name = "*" |
||||||
|
out.Values[i].Value = l.Value |
||||||
|
} else { |
||||||
|
out.Values[i] = l |
||||||
|
} |
||||||
|
} |
||||||
|
return out |
||||||
|
} |
||||||
|
|
||||||
|
// Call is an item in the stack trace.
|
||||||
|
type Call struct { |
||||||
|
SourcePath string // Full path name of the source file
|
||||||
|
Line int // Line number
|
||||||
|
Func Function // Fully qualified function name (encoded).
|
||||||
|
Args Args // Call arguments
|
||||||
|
} |
||||||
|
|
||||||
|
// Equal returns true only if both calls are exactly equal.
|
||||||
|
func (c *Call) Equal(r *Call) bool { |
||||||
|
return c.SourcePath == r.SourcePath && c.Line == r.Line && c.Func == r.Func && c.Args.Equal(&r.Args) |
||||||
|
} |
||||||
|
|
||||||
|
// Similar returns true if the two Call are equal or almost but not quite
|
||||||
|
// equal.
|
||||||
|
func (c *Call) Similar(r *Call, similar Similarity) bool { |
||||||
|
return c.SourcePath == r.SourcePath && c.Line == r.Line && c.Func == r.Func && c.Args.Similar(&r.Args, similar) |
||||||
|
} |
||||||
|
|
||||||
|
// Merge merges two similar Call, zapping out differences.
|
||||||
|
func (c *Call) Merge(r *Call) Call { |
||||||
|
return Call{ |
||||||
|
SourcePath: c.SourcePath, |
||||||
|
Line: c.Line, |
||||||
|
Func: c.Func, |
||||||
|
Args: c.Args.Merge(&r.Args), |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// SourceName returns the base file name of the source file.
|
||||||
|
func (c *Call) SourceName() string { |
||||||
|
return filepath.Base(c.SourcePath) |
||||||
|
} |
||||||
|
|
||||||
|
// SourceLine returns "source.go:line", including only the base file name.
|
||||||
|
func (c *Call) SourceLine() string { |
||||||
|
return fmt.Sprintf("%s:%d", c.SourceName(), c.Line) |
||||||
|
} |
||||||
|
|
||||||
|
// FullSourceLine returns "/path/to/source.go:line".
|
||||||
|
func (c *Call) FullSourceLine() string { |
||||||
|
return fmt.Sprintf("%s:%d", c.SourcePath, c.Line) |
||||||
|
} |
||||||
|
|
||||||
|
// PkgSource is one directory plus the file name of the source file.
|
||||||
|
func (c *Call) PkgSource() string { |
||||||
|
return filepath.Join(filepath.Base(filepath.Dir(c.SourcePath)), c.SourceName()) |
||||||
|
} |
||||||
|
|
||||||
|
const testMainSource = "_test" + string(os.PathSeparator) + "_testmain.go" |
||||||
|
|
||||||
|
// IsStdlib returns true if it is a Go standard library function. This includes
|
||||||
|
// the 'go test' generated main executable.
|
||||||
|
func (c *Call) IsStdlib() bool { |
||||||
|
for _, goroot := range goroots { |
||||||
|
if strings.HasPrefix(c.SourcePath, goroot) { |
||||||
|
return true |
||||||
|
} |
||||||
|
} |
||||||
|
// Consider _test/_testmain.go as stdlib since it's injected by "go test".
|
||||||
|
return c.PkgSource() == testMainSource |
||||||
|
} |
||||||
|
|
||||||
|
// IsPkgMain returns true if it is in the main package.
|
||||||
|
func (c *Call) IsPkgMain() bool { |
||||||
|
return c.Func.PkgName() == "main" |
||||||
|
} |
||||||
|
|
||||||
|
// Stack is a call stack.
|
||||||
|
type Stack struct { |
||||||
|
Calls []Call // Call stack. First is original function, last is leaf function.
|
||||||
|
Elided bool // Happens when there's >100 items in Stack, currently hardcoded in package runtime.
|
||||||
|
} |
||||||
|
|
||||||
|
// Equal returns true on if both call stacks are exactly equal.
|
||||||
|
func (s *Stack) Equal(r *Stack) bool { |
||||||
|
if len(s.Calls) != len(r.Calls) || s.Elided != r.Elided { |
||||||
|
return false |
||||||
|
} |
||||||
|
for i := range s.Calls { |
||||||
|
if !s.Calls[i].Equal(&r.Calls[i]) { |
||||||
|
return false |
||||||
|
} |
||||||
|
} |
||||||
|
return true |
||||||
|
} |
||||||
|
|
||||||
|
// Similar returns true if the two Stack are equal or almost but not quite
|
||||||
|
// equal.
|
||||||
|
func (s *Stack) Similar(r *Stack, similar Similarity) bool { |
||||||
|
if len(s.Calls) != len(r.Calls) || s.Elided != r.Elided { |
||||||
|
return false |
||||||
|
} |
||||||
|
for i := range s.Calls { |
||||||
|
if !s.Calls[i].Similar(&r.Calls[i], similar) { |
||||||
|
return false |
||||||
|
} |
||||||
|
} |
||||||
|
return true |
||||||
|
} |
||||||
|
|
||||||
|
// Merge merges two similar Stack, zapping out differences.
|
||||||
|
func (s *Stack) Merge(r *Stack) *Stack { |
||||||
|
// Assumes similar stacks have the same length.
|
||||||
|
out := &Stack{ |
||||||
|
Calls: make([]Call, len(s.Calls)), |
||||||
|
Elided: s.Elided, |
||||||
|
} |
||||||
|
for i := range s.Calls { |
||||||
|
out.Calls[i] = s.Calls[i].Merge(&r.Calls[i]) |
||||||
|
} |
||||||
|
return out |
||||||
|
} |
||||||
|
|
||||||
|
// Less compares two Stack, where the ones that are less are more
|
||||||
|
// important, so they come up front. A Stack with more private functions is
|
||||||
|
// 'less' so it is at the top. Inversely, a Stack with only public
|
||||||
|
// functions is 'more' so it is at the bottom.
|
||||||
|
func (s *Stack) Less(r *Stack) bool { |
||||||
|
lStdlib := 0 |
||||||
|
lPrivate := 0 |
||||||
|
for _, c := range s.Calls { |
||||||
|
if c.IsStdlib() { |
||||||
|
lStdlib++ |
||||||
|
} else { |
||||||
|
lPrivate++ |
||||||
|
} |
||||||
|
} |
||||||
|
rStdlib := 0 |
||||||
|
rPrivate := 0 |
||||||
|
for _, s := range r.Calls { |
||||||
|
if s.IsStdlib() { |
||||||
|
rStdlib++ |
||||||
|
} else { |
||||||
|
rPrivate++ |
||||||
|
} |
||||||
|
} |
||||||
|
if lPrivate > rPrivate { |
||||||
|
return true |
||||||
|
} |
||||||
|
if lPrivate < rPrivate { |
||||||
|
return false |
||||||
|
} |
||||||
|
if lStdlib > rStdlib { |
||||||
|
return false |
||||||
|
} |
||||||
|
if lStdlib < rStdlib { |
||||||
|
return true |
||||||
|
} |
||||||
|
|
||||||
|
// Stack lengths are the same.
|
||||||
|
for x := range s.Calls { |
||||||
|
if s.Calls[x].Func.Raw < r.Calls[x].Func.Raw { |
||||||
|
return true |
||||||
|
} |
||||||
|
if s.Calls[x].Func.Raw > r.Calls[x].Func.Raw { |
||||||
|
return true |
||||||
|
} |
||||||
|
if s.Calls[x].PkgSource() < r.Calls[x].PkgSource() { |
||||||
|
return true |
||||||
|
} |
||||||
|
if s.Calls[x].PkgSource() > r.Calls[x].PkgSource() { |
||||||
|
return true |
||||||
|
} |
||||||
|
if s.Calls[x].Line < r.Calls[x].Line { |
||||||
|
return true |
||||||
|
} |
||||||
|
if s.Calls[x].Line > r.Calls[x].Line { |
||||||
|
return true |
||||||
|
} |
||||||
|
} |
||||||
|
return false |
||||||
|
} |
||||||
|
|
||||||
|
// Signature represents the signature of one or multiple goroutines.
|
||||||
|
//
|
||||||
|
// It is effectively the stack trace plus the goroutine internal bits, like
|
||||||
|
// it's state, if it is thread locked, which call site created this goroutine,
|
||||||
|
// etc.
|
||||||
|
type Signature struct { |
||||||
|
// Use git grep 'gopark(|unlock)\(' to find them all plus everything listed
|
||||||
|
// in runtime/traceback.go. Valid values includes:
|
||||||
|
// - chan send, chan receive, select
|
||||||
|
// - finalizer wait, mark wait (idle),
|
||||||
|
// - Concurrent GC wait, GC sweep wait, force gc (idle)
|
||||||
|
// - IO wait, panicwait
|
||||||
|
// - semacquire, semarelease
|
||||||
|
// - sleep, timer goroutine (idle)
|
||||||
|
// - trace reader (blocked)
|
||||||
|
// Stuck cases:
|
||||||
|
// - chan send (nil chan), chan receive (nil chan), select (no cases)
|
||||||
|
// Runnable states:
|
||||||
|
// - idle, runnable, running, syscall, waiting, dead, enqueue, copystack,
|
||||||
|
// Scan states:
|
||||||
|
// - scan, scanrunnable, scanrunning, scansyscall, scanwaiting, scandead,
|
||||||
|
// scanenqueue
|
||||||
|
State string |
||||||
|
CreatedBy Call // Which other goroutine which created this one.
|
||||||
|
SleepMin int // Wait time in minutes, if applicable.
|
||||||
|
SleepMax int // Wait time in minutes, if applicable.
|
||||||
|
Stack Stack |
||||||
|
Locked bool // Locked to an OS thread.
|
||||||
|
} |
||||||
|
|
||||||
|
// Equal returns true only if both signatures are exactly equal.
|
||||||
|
func (s *Signature) Equal(r *Signature) bool { |
||||||
|
if s.State != r.State || !s.CreatedBy.Equal(&r.CreatedBy) || s.Locked != r.Locked || s.SleepMin != r.SleepMin || s.SleepMax != r.SleepMax { |
||||||
|
return false |
||||||
|
} |
||||||
|
return s.Stack.Equal(&r.Stack) |
||||||
|
} |
||||||
|
|
||||||
|
// Similar returns true if the two Signature are equal or almost but not quite
|
||||||
|
// equal.
|
||||||
|
func (s *Signature) Similar(r *Signature, similar Similarity) bool { |
||||||
|
if s.State != r.State || !s.CreatedBy.Similar(&r.CreatedBy, similar) { |
||||||
|
return false |
||||||
|
} |
||||||
|
if similar == ExactFlags && s.Locked != r.Locked { |
||||||
|
return false |
||||||
|
} |
||||||
|
return s.Stack.Similar(&r.Stack, similar) |
||||||
|
} |
||||||
|
|
||||||
|
// Merge merges two similar Signature, zapping out differences.
|
||||||
|
func (s *Signature) Merge(r *Signature) *Signature { |
||||||
|
min := s.SleepMin |
||||||
|
if r.SleepMin < min { |
||||||
|
min = r.SleepMin |
||||||
|
} |
||||||
|
max := s.SleepMax |
||||||
|
if r.SleepMax > max { |
||||||
|
max = r.SleepMax |
||||||
|
} |
||||||
|
return &Signature{ |
||||||
|
State: s.State, // Drop right side.
|
||||||
|
CreatedBy: s.CreatedBy, // Drop right side.
|
||||||
|
SleepMin: min, |
||||||
|
SleepMax: max, |
||||||
|
Stack: *s.Stack.Merge(&r.Stack), |
||||||
|
Locked: s.Locked || r.Locked, // TODO(maruel): This is weirdo.
|
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Less compares two Signature, where the ones that are less are more
|
||||||
|
// important, so they come up front. A Signature with more private functions is
|
||||||
|
// 'less' so it is at the top. Inversely, a Signature with only public
|
||||||
|
// functions is 'more' so it is at the bottom.
|
||||||
|
func (s *Signature) Less(r *Signature) bool { |
||||||
|
if s.Stack.Less(&r.Stack) { |
||||||
|
return true |
||||||
|
} |
||||||
|
if r.Stack.Less(&s.Stack) { |
||||||
|
return false |
||||||
|
} |
||||||
|
if s.Locked && !r.Locked { |
||||||
|
return true |
||||||
|
} |
||||||
|
if r.Locked && !s.Locked { |
||||||
|
return false |
||||||
|
} |
||||||
|
if s.State < r.State { |
||||||
|
return true |
||||||
|
} |
||||||
|
if s.State > r.State { |
||||||
|
return false |
||||||
|
} |
||||||
|
return false |
||||||
|
} |
||||||
|
|
||||||
|
// Goroutine represents the state of one goroutine, including the stack trace.
|
||||||
|
type Goroutine struct { |
||||||
|
Signature // It's stack trace, internal bits, state, which call site created it, etc.
|
||||||
|
ID int // Goroutine ID.
|
||||||
|
First bool // First is the goroutine first printed, normally the one that crashed.
|
||||||
|
} |
||||||
|
|
||||||
|
// Bucketize returns the number of similar goroutines.
|
||||||
|
func Bucketize(goroutines []Goroutine, similar Similarity) map[*Signature][]Goroutine { |
||||||
|
out := map[*Signature][]Goroutine{} |
||||||
|
// O(n²). Fix eventually.
|
||||||
|
for _, routine := range goroutines { |
||||||
|
found := false |
||||||
|
for key := range out { |
||||||
|
// When a match is found, this effectively drops the other goroutine ID.
|
||||||
|
if key.Similar(&routine.Signature, similar) { |
||||||
|
found = true |
||||||
|
if !key.Equal(&routine.Signature) { |
||||||
|
// Almost but not quite equal. There's different pointers passed
|
||||||
|
// around but the same values. Zap out the different values.
|
||||||
|
newKey := key.Merge(&routine.Signature) |
||||||
|
out[newKey] = append(out[key], routine) |
||||||
|
delete(out, key) |
||||||
|
} else { |
||||||
|
out[key] = append(out[key], routine) |
||||||
|
} |
||||||
|
break |
||||||
|
} |
||||||
|
} |
||||||
|
if !found { |
||||||
|
key := &Signature{} |
||||||
|
*key = routine.Signature |
||||||
|
out[key] = []Goroutine{routine} |
||||||
|
} |
||||||
|
} |
||||||
|
return out |
||||||
|
} |
||||||
|
|
||||||
|
// Bucket is a stack trace signature and the list of goroutines that fits this
|
||||||
|
// signature.
|
||||||
|
type Bucket struct { |
||||||
|
Signature |
||||||
|
Routines []Goroutine |
||||||
|
} |
||||||
|
|
||||||
|
// First returns true if it contains the first goroutine, e.g. the ones that
|
||||||
|
// likely generated the panic() call, if any.
|
||||||
|
func (b *Bucket) First() bool { |
||||||
|
for _, r := range b.Routines { |
||||||
|
if r.First { |
||||||
|
return true |
||||||
|
} |
||||||
|
} |
||||||
|
return false |
||||||
|
} |
||||||
|
|
||||||
|
// Less does reverse sort.
|
||||||
|
func (b *Bucket) Less(r *Bucket) bool { |
||||||
|
if b.First() { |
||||||
|
return true |
||||||
|
} |
||||||
|
if r.First() { |
||||||
|
return false |
||||||
|
} |
||||||
|
return b.Signature.Less(&r.Signature) |
||||||
|
} |
||||||
|
|
||||||
|
// Buckets is a list of Bucket sorted by repeation count.
|
||||||
|
type Buckets []Bucket |
||||||
|
|
||||||
|
func (b Buckets) Len() int { |
||||||
|
return len(b) |
||||||
|
} |
||||||
|
|
||||||
|
func (b Buckets) Less(i, j int) bool { |
||||||
|
return b[i].Less(&b[j]) |
||||||
|
} |
||||||
|
|
||||||
|
func (b Buckets) Swap(i, j int) { |
||||||
|
b[j], b[i] = b[i], b[j] |
||||||
|
} |
||||||
|
|
||||||
|
// SortBuckets creates a list of Bucket from each goroutine stack trace count.
|
||||||
|
func SortBuckets(buckets map[*Signature][]Goroutine) Buckets { |
||||||
|
out := make(Buckets, 0, len(buckets)) |
||||||
|
for signature, count := range buckets { |
||||||
|
out = append(out, Bucket{*signature, count}) |
||||||
|
} |
||||||
|
sort.Sort(out) |
||||||
|
return out |
||||||
|
} |
||||||
|
|
||||||
|
// scanLines is similar to bufio.ScanLines except that it:
|
||||||
|
// - doesn't drop '\n'
|
||||||
|
// - doesn't strip '\r'
|
||||||
|
// - returns when the data is bufio.MaxScanTokenSize bytes
|
||||||
|
func scanLines(data []byte, atEOF bool) (advance int, token []byte, err error) { |
||||||
|
if atEOF && len(data) == 0 { |
||||||
|
return 0, nil, nil |
||||||
|
} |
||||||
|
if i := bytes.IndexByte(data, '\n'); i >= 0 { |
||||||
|
return i + 1, data[0 : i+1], nil |
||||||
|
} |
||||||
|
if atEOF { |
||||||
|
return len(data), data, nil |
||||||
|
} |
||||||
|
if len(data) >= bufio.MaxScanTokenSize { |
||||||
|
// Returns the line even if it is not at EOF nor has a '\n', otherwise the
|
||||||
|
// scanner will return bufio.ErrTooLong which is definitely not what we
|
||||||
|
// want.
|
||||||
|
return len(data), data, nil |
||||||
|
} |
||||||
|
return 0, nil, nil |
||||||
|
} |
||||||
|
|
||||||
|
// ParseDump processes the output from runtime.Stack().
|
||||||
|
//
|
||||||
|
// It supports piping from another command and assumes there is junk before the
|
||||||
|
// actual stack trace. The junk is streamed to out.
|
||||||
|
func ParseDump(r io.Reader, out io.Writer) ([]Goroutine, error) { |
||||||
|
goroutines := make([]Goroutine, 0, 16) |
||||||
|
var goroutine *Goroutine |
||||||
|
scanner := bufio.NewScanner(r) |
||||||
|
scanner.Split(scanLines) |
||||||
|
// TODO(maruel): Use a formal state machine. Patterns follows:
|
||||||
|
// - reRoutineHeader
|
||||||
|
// Either:
|
||||||
|
// - reUnavail
|
||||||
|
// - reFunc + reFile in a loop
|
||||||
|
// - reElided
|
||||||
|
// Optionally ends with:
|
||||||
|
// - reCreated + reFile
|
||||||
|
// Between each goroutine stack dump: an empty line
|
||||||
|
created := false |
||||||
|
// firstLine is the first line after the reRoutineHeader header line.
|
||||||
|
firstLine := false |
||||||
|
for scanner.Scan() { |
||||||
|
line := scanner.Text() |
||||||
|
if line == "\n" { |
||||||
|
if goroutine != nil { |
||||||
|
goroutine = nil |
||||||
|
continue |
||||||
|
} |
||||||
|
} else if line[len(line)-1] == '\n' { |
||||||
|
if goroutine == nil { |
||||||
|
if match := reRoutineHeader.FindStringSubmatch(line); match != nil { |
||||||
|
if id, err := strconv.Atoi(match[1]); err == nil { |
||||||
|
// See runtime/traceback.go.
|
||||||
|
// "<state>, \d+ minutes, locked to thread"
|
||||||
|
items := strings.Split(match[2], ", ") |
||||||
|
sleep := 0 |
||||||
|
locked := false |
||||||
|
for i := 1; i < len(items); i++ { |
||||||
|
if items[i] == lockedToThread { |
||||||
|
locked = true |
||||||
|
continue |
||||||
|
} |
||||||
|
// Look for duration, if any.
|
||||||
|
if match2 := reMinutes.FindStringSubmatch(items[i]); match2 != nil { |
||||||
|
sleep, _ = strconv.Atoi(match2[1]) |
||||||
|
} |
||||||
|
} |
||||||
|
goroutines = append(goroutines, Goroutine{ |
||||||
|
Signature: Signature{ |
||||||
|
State: items[0], |
||||||
|
SleepMin: sleep, |
||||||
|
SleepMax: sleep, |
||||||
|
Locked: locked, |
||||||
|
}, |
||||||
|
ID: id, |
||||||
|
First: len(goroutines) == 0, |
||||||
|
}) |
||||||
|
goroutine = &goroutines[len(goroutines)-1] |
||||||
|
firstLine = true |
||||||
|
continue |
||||||
|
} |
||||||
|
} |
||||||
|
} else { |
||||||
|
if firstLine { |
||||||
|
firstLine = false |
||||||
|
if match := reUnavail.FindStringSubmatch(line); match != nil { |
||||||
|
// Generate a fake stack entry.
|
||||||
|
goroutine.Stack.Calls = []Call{{SourcePath: "<unavailable>"}} |
||||||
|
continue |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if match := reFile.FindStringSubmatch(line); match != nil { |
||||||
|
// Triggers after a reFunc or a reCreated.
|
||||||
|
num, err := strconv.Atoi(match[2]) |
||||||
|
if err != nil { |
||||||
|
return goroutines, fmt.Errorf("failed to parse int on line: \"%s\"", line) |
||||||
|
} |
||||||
|
if created { |
||||||
|
created = false |
||||||
|
goroutine.CreatedBy.SourcePath = match[1] |
||||||
|
goroutine.CreatedBy.Line = num |
||||||
|
} else { |
||||||
|
i := len(goroutine.Stack.Calls) - 1 |
||||||
|
if i < 0 { |
||||||
|
return goroutines, errors.New("unexpected order") |
||||||
|
} |
||||||
|
goroutine.Stack.Calls[i].SourcePath = match[1] |
||||||
|
goroutine.Stack.Calls[i].Line = num |
||||||
|
} |
||||||
|
continue |
||||||
|
} |
||||||
|
|
||||||
|
if match := reCreated.FindStringSubmatch(line); match != nil { |
||||||
|
created = true |
||||||
|
goroutine.CreatedBy.Func.Raw = match[1] |
||||||
|
continue |
||||||
|
} |
||||||
|
|
||||||
|
if match := reFunc.FindStringSubmatch(line); match != nil { |
||||||
|
args := Args{} |
||||||
|
for _, a := range strings.Split(match[2], ", ") { |
||||||
|
if a == "..." { |
||||||
|
args.Elided = true |
||||||
|
continue |
||||||
|
} |
||||||
|
if a == "" { |
||||||
|
// Remaining values were dropped.
|
||||||
|
break |
||||||
|
} |
||||||
|
v, err := strconv.ParseUint(a, 0, 64) |
||||||
|
if err != nil { |
||||||
|
return goroutines, fmt.Errorf("failed to parse int on line: \"%s\"", line) |
||||||
|
} |
||||||
|
args.Values = append(args.Values, Arg{Value: v}) |
||||||
|
} |
||||||
|
goroutine.Stack.Calls = append(goroutine.Stack.Calls, Call{Func: Function{match[1]}, Args: args}) |
||||||
|
continue |
||||||
|
} |
||||||
|
|
||||||
|
if match := reElided.FindStringSubmatch(line); match != nil { |
||||||
|
goroutine.Stack.Elided = true |
||||||
|
continue |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
_, _ = io.WriteString(out, line) |
||||||
|
goroutine = nil |
||||||
|
} |
||||||
|
nameArguments(goroutines) |
||||||
|
return goroutines, scanner.Err() |
||||||
|
} |
||||||
|
|
||||||
|
// Private stuff.
|
||||||
|
|
||||||
|
func nameArguments(goroutines []Goroutine) { |
||||||
|
// Set a name for any pointer occuring more than once.
|
||||||
|
type object struct { |
||||||
|
args []*Arg |
||||||
|
inPrimary bool |
||||||
|
id int |
||||||
|
} |
||||||
|
objects := map[uint64]object{} |
||||||
|
// Enumerate all the arguments.
|
||||||
|
for i := range goroutines { |
||||||
|
for j := range goroutines[i].Stack.Calls { |
||||||
|
for k := range goroutines[i].Stack.Calls[j].Args.Values { |
||||||
|
arg := goroutines[i].Stack.Calls[j].Args.Values[k] |
||||||
|
if arg.IsPtr() { |
||||||
|
objects[arg.Value] = object{ |
||||||
|
args: append(objects[arg.Value].args, &goroutines[i].Stack.Calls[j].Args.Values[k]), |
||||||
|
inPrimary: objects[arg.Value].inPrimary || i == 0, |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
// CreatedBy.Args is never set.
|
||||||
|
} |
||||||
|
order := uint64Slice{} |
||||||
|
for k, obj := range objects { |
||||||
|
if len(obj.args) > 1 && obj.inPrimary { |
||||||
|
order = append(order, k) |
||||||
|
} |
||||||
|
} |
||||||
|
sort.Sort(order) |
||||||
|
nextID := 1 |
||||||
|
for _, k := range order { |
||||||
|
for _, arg := range objects[k].args { |
||||||
|
arg.Name = fmt.Sprintf("#%d", nextID) |
||||||
|
} |
||||||
|
nextID++ |
||||||
|
} |
||||||
|
|
||||||
|
// Now do the rest. This is done so the output is deterministic.
|
||||||
|
order = uint64Slice{} |
||||||
|
for k := range objects { |
||||||
|
order = append(order, k) |
||||||
|
} |
||||||
|
sort.Sort(order) |
||||||
|
for _, k := range order { |
||||||
|
// Process the remaining pointers, they were not referenced by primary
|
||||||
|
// thread so will have higher IDs.
|
||||||
|
if objects[k].inPrimary { |
||||||
|
continue |
||||||
|
} |
||||||
|
for _, arg := range objects[k].args { |
||||||
|
arg.Name = fmt.Sprintf("#%d", nextID) |
||||||
|
} |
||||||
|
nextID++ |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
type uint64Slice []uint64 |
||||||
|
|
||||||
|
func (a uint64Slice) Len() int { return len(a) } |
||||||
|
func (a uint64Slice) Swap(i, j int) { a[i], a[j] = a[j], a[i] } |
||||||
|
func (a uint64Slice) Less(i, j int) bool { return a[i] < a[j] } |
@ -0,0 +1,139 @@ |
|||||||
|
// Copyright 2016 Marc-Antoine Ruel. All rights reserved.
|
||||||
|
// Use of this source code is governed under the Apache License, Version 2.0
|
||||||
|
// that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package stack |
||||||
|
|
||||||
|
import ( |
||||||
|
"fmt" |
||||||
|
"strings" |
||||||
|
) |
||||||
|
|
||||||
|
// Palette defines the color used.
|
||||||
|
//
|
||||||
|
// An empty object Palette{} can be used to disable coloring.
|
||||||
|
type Palette struct { |
||||||
|
EOLReset string |
||||||
|
|
||||||
|
// Routine header.
|
||||||
|
RoutineFirst string // The first routine printed.
|
||||||
|
Routine string // Following routines.
|
||||||
|
CreatedBy string |
||||||
|
|
||||||
|
// Call line.
|
||||||
|
Package string |
||||||
|
SourceFile string |
||||||
|
FunctionStdLib string |
||||||
|
FunctionStdLibExported string |
||||||
|
FunctionMain string |
||||||
|
FunctionOther string |
||||||
|
FunctionOtherExported string |
||||||
|
Arguments string |
||||||
|
} |
||||||
|
|
||||||
|
// CalcLengths returns the maximum length of the source lines and package names.
|
||||||
|
func CalcLengths(buckets Buckets, fullPath bool) (int, int) { |
||||||
|
srcLen := 0 |
||||||
|
pkgLen := 0 |
||||||
|
for _, bucket := range buckets { |
||||||
|
for _, line := range bucket.Signature.Stack.Calls { |
||||||
|
l := 0 |
||||||
|
if fullPath { |
||||||
|
l = len(line.FullSourceLine()) |
||||||
|
} else { |
||||||
|
l = len(line.SourceLine()) |
||||||
|
} |
||||||
|
if l > srcLen { |
||||||
|
srcLen = l |
||||||
|
} |
||||||
|
l = len(line.Func.PkgName()) |
||||||
|
if l > pkgLen { |
||||||
|
pkgLen = l |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return srcLen, pkgLen |
||||||
|
} |
||||||
|
|
||||||
|
// functionColor returns the color to be used for the function name based on
|
||||||
|
// the type of package the function is in.
|
||||||
|
func (p *Palette) functionColor(line *Call) string { |
||||||
|
if line.IsStdlib() { |
||||||
|
if line.Func.IsExported() { |
||||||
|
return p.FunctionStdLibExported |
||||||
|
} |
||||||
|
return p.FunctionStdLib |
||||||
|
} else if line.IsPkgMain() { |
||||||
|
return p.FunctionMain |
||||||
|
} else if line.Func.IsExported() { |
||||||
|
return p.FunctionOtherExported |
||||||
|
} |
||||||
|
return p.FunctionOther |
||||||
|
} |
||||||
|
|
||||||
|
// routineColor returns the color for the header of the goroutines bucket.
|
||||||
|
func (p *Palette) routineColor(bucket *Bucket, multipleBuckets bool) string { |
||||||
|
if bucket.First() && multipleBuckets { |
||||||
|
return p.RoutineFirst |
||||||
|
} |
||||||
|
return p.Routine |
||||||
|
} |
||||||
|
|
||||||
|
// BucketHeader prints the header of a goroutine signature.
|
||||||
|
func (p *Palette) BucketHeader(bucket *Bucket, fullPath, multipleBuckets bool) string { |
||||||
|
extra := "" |
||||||
|
if bucket.SleepMax != 0 { |
||||||
|
if bucket.SleepMin != bucket.SleepMax { |
||||||
|
extra += fmt.Sprintf(" [%d~%d minutes]", bucket.SleepMin, bucket.SleepMax) |
||||||
|
} else { |
||||||
|
extra += fmt.Sprintf(" [%d minutes]", bucket.SleepMax) |
||||||
|
} |
||||||
|
} |
||||||
|
if bucket.Locked { |
||||||
|
extra += " [locked]" |
||||||
|
} |
||||||
|
created := bucket.CreatedBy.Func.PkgDotName() |
||||||
|
if created != "" { |
||||||
|
created += " @ " |
||||||
|
if fullPath { |
||||||
|
created += bucket.CreatedBy.FullSourceLine() |
||||||
|
} else { |
||||||
|
created += bucket.CreatedBy.SourceLine() |
||||||
|
} |
||||||
|
extra += p.CreatedBy + " [Created by " + created + "]" |
||||||
|
} |
||||||
|
return fmt.Sprintf( |
||||||
|
"%s%d: %s%s%s\n", |
||||||
|
p.routineColor(bucket, multipleBuckets), len(bucket.Routines), |
||||||
|
bucket.State, extra, |
||||||
|
p.EOLReset) |
||||||
|
} |
||||||
|
|
||||||
|
// callLine prints one stack line.
|
||||||
|
func (p *Palette) callLine(line *Call, srcLen, pkgLen int, fullPath bool) string { |
||||||
|
src := "" |
||||||
|
if fullPath { |
||||||
|
src = line.FullSourceLine() |
||||||
|
} else { |
||||||
|
src = line.SourceLine() |
||||||
|
} |
||||||
|
return fmt.Sprintf( |
||||||
|
" %s%-*s %s%-*s %s%s%s(%s)%s", |
||||||
|
p.Package, pkgLen, line.Func.PkgName(), |
||||||
|
p.SourceFile, srcLen, src, |
||||||
|
p.functionColor(line), line.Func.Name(), |
||||||
|
p.Arguments, line.Args, |
||||||
|
p.EOLReset) |
||||||
|
} |
||||||
|
|
||||||
|
// StackLines prints one complete stack trace, without the header.
|
||||||
|
func (p *Palette) StackLines(signature *Signature, srcLen, pkgLen int, fullPath bool) string { |
||||||
|
out := make([]string, len(signature.Stack.Calls)) |
||||||
|
for i := range signature.Stack.Calls { |
||||||
|
out[i] = p.callLine(&signature.Stack.Calls[i], srcLen, pkgLen, fullPath) |
||||||
|
} |
||||||
|
if signature.Stack.Elided { |
||||||
|
out = append(out, " (...)") |
||||||
|
} |
||||||
|
return strings.Join(out, "\n") + "\n" |
||||||
|
} |
@ -0,0 +1,17 @@ |
|||||||
|
vendors: |
||||||
|
- path: github.com/kr/pretty |
||||||
|
rev: 737b74a46c4bf788349f72cb256fed10aea4d0ac |
||||||
|
- path: github.com/kr/text |
||||||
|
rev: 7cafcd837844e784b526369c9bce262804aebc60 |
||||||
|
- path: github.com/maruel/ut |
||||||
|
rev: a9c9f15ccfa6f8b90182a53df32f4745586fbae3 |
||||||
|
- path: github.com/mattn/go-colorable |
||||||
|
rev: 9056b7a9f2d1f2d96498d6d146acd1f9d5ed3d59 |
||||||
|
- path: github.com/mattn/go-isatty |
||||||
|
rev: 56b76bdf51f7708750eac80fa38b952bb9f32639 |
||||||
|
- path: github.com/mgutz/ansi |
||||||
|
rev: c286dcecd19ff979eeb73ea444e479b903f2cfcb |
||||||
|
- path: github.com/pmezard/go-difflib |
||||||
|
rev: 792786c7400a136282c1664665ae0a8db921c6c2 |
||||||
|
- path: golang.org/x/sys |
||||||
|
rev: a646d33e2ee3172a661fc09bca23bb4889a41bc8 |
@ -0,0 +1,31 @@ |
|||||||
|
// Copyright 2016 The Go Authors. All rights reserved. |
||||||
|
// Use of this source code is governed by a BSD-style |
||||||
|
// license that can be found in the LICENSE file. |
||||||
|
|
||||||
|
// +build linux |
||||||
|
// +build mips mipsle |
||||||
|
// +build !gccgo |
||||||
|
|
||||||
|
#include "textflag.h" |
||||||
|
|
||||||
|
// |
||||||
|
// System calls for mips, Linux |
||||||
|
// |
||||||
|
|
||||||
|
// Just jump to package syscall's implementation for all these functions. |
||||||
|
// The runtime may know about them. |
||||||
|
|
||||||
|
TEXT ·Syscall(SB),NOSPLIT,$0-28 |
||||||
|
JMP syscall·Syscall(SB) |
||||||
|
|
||||||
|
TEXT ·Syscall6(SB),NOSPLIT,$0-40 |
||||||
|
JMP syscall·Syscall6(SB) |
||||||
|
|
||||||
|
TEXT ·Syscall9(SB),NOSPLIT,$0-52 |
||||||
|
JMP syscall·Syscall9(SB) |
||||||
|
|
||||||
|
TEXT ·RawSyscall(SB),NOSPLIT,$0-28 |
||||||
|
JMP syscall·RawSyscall(SB) |
||||||
|
|
||||||
|
TEXT ·RawSyscall6(SB),NOSPLIT,$0-40 |
||||||
|
JMP syscall·RawSyscall6(SB) |
@ -0,0 +1,13 @@ |
|||||||
|
// Copyright 2016 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build amd64,linux
|
||||||
|
// +build !gccgo
|
||||||
|
|
||||||
|
package unix |
||||||
|
|
||||||
|
import "syscall" |
||||||
|
|
||||||
|
//go:noescape
|
||||||
|
func gettimeofday(tv *Timeval) (err syscall.Errno) |
@ -0,0 +1,241 @@ |
|||||||
|
// Copyright 2016 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build linux
|
||||||
|
// +build mips mipsle
|
||||||
|
|
||||||
|
package unix |
||||||
|
|
||||||
|
import ( |
||||||
|
"syscall" |
||||||
|
"unsafe" |
||||||
|
) |
||||||
|
|
||||||
|
func Syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno) |
||||||
|
|
||||||
|
//sys Dup2(oldfd int, newfd int) (err error)
|
||||||
|
//sys Fchown(fd int, uid int, gid int) (err error)
|
||||||
|
//sys Ftruncate(fd int, length int64) (err error) = SYS_FTRUNCATE64
|
||||||
|
//sysnb Getegid() (egid int)
|
||||||
|
//sysnb Geteuid() (euid int)
|
||||||
|
//sysnb Getgid() (gid int)
|
||||||
|
//sysnb Getuid() (uid int)
|
||||||
|
//sys Lchown(path string, uid int, gid int) (err error)
|
||||||
|
//sys Listen(s int, n int) (err error)
|
||||||
|
//sys Pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64
|
||||||
|
//sys Pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64
|
||||||
|
//sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) = SYS__NEWSELECT
|
||||||
|
//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) = SYS_SENDFILE64
|
||||||
|
//sys Setfsgid(gid int) (err error)
|
||||||
|
//sys Setfsuid(uid int) (err error)
|
||||||
|
//sysnb Setregid(rgid int, egid int) (err error)
|
||||||
|
//sysnb Setresgid(rgid int, egid int, sgid int) (err error)
|
||||||
|
//sysnb Setresuid(ruid int, euid int, suid int) (err error)
|
||||||
|
|
||||||
|
//sysnb Setreuid(ruid int, euid int) (err error)
|
||||||
|
//sys Shutdown(fd int, how int) (err error)
|
||||||
|
//sys Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error)
|
||||||
|
|
||||||
|
//sys SyncFileRange(fd int, off int64, n int64, flags int) (err error)
|
||||||
|
//sys Truncate(path string, length int64) (err error) = SYS_TRUNCATE64
|
||||||
|
//sys accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error)
|
||||||
|
//sys accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error)
|
||||||
|
//sys bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error)
|
||||||
|
//sys connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error)
|
||||||
|
//sysnb getgroups(n int, list *_Gid_t) (nn int, err error)
|
||||||
|
//sysnb setgroups(n int, list *_Gid_t) (err error)
|
||||||
|
//sys getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error)
|
||||||
|
//sys setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error)
|
||||||
|
//sysnb socket(domain int, typ int, proto int) (fd int, err error)
|
||||||
|
//sysnb socketpair(domain int, typ int, proto int, fd *[2]int32) (err error)
|
||||||
|
//sysnb getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error)
|
||||||
|
//sysnb getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error)
|
||||||
|
//sys recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error)
|
||||||
|
//sys sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error)
|
||||||
|
//sys recvmsg(s int, msg *Msghdr, flags int) (n int, err error)
|
||||||
|
//sys sendmsg(s int, msg *Msghdr, flags int) (n int, err error)
|
||||||
|
|
||||||
|
//sysnb InotifyInit() (fd int, err error)
|
||||||
|
//sys Ioperm(from int, num int, on int) (err error)
|
||||||
|
//sys Iopl(level int) (err error)
|
||||||
|
|
||||||
|
//sysnb Gettimeofday(tv *Timeval) (err error)
|
||||||
|
//sysnb Time(t *Time_t) (tt Time_t, err error)
|
||||||
|
|
||||||
|
//sys Lstat(path string, stat *Stat_t) (err error) = SYS_LSTAT64
|
||||||
|
//sys Fstat(fd int, stat *Stat_t) (err error) = SYS_FSTAT64
|
||||||
|
//sys Stat(path string, stat *Stat_t) (err error) = SYS_STAT64
|
||||||
|
|
||||||
|
//sys Utime(path string, buf *Utimbuf) (err error)
|
||||||
|
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
|
||||||
|
//sys Pause() (err error)
|
||||||
|
|
||||||
|
func Fstatfs(fd int, buf *Statfs_t) (err error) { |
||||||
|
_, _, e := Syscall(SYS_FSTATFS64, uintptr(fd), unsafe.Sizeof(*buf), uintptr(unsafe.Pointer(buf))) |
||||||
|
use(unsafe.Pointer(buf)) |
||||||
|
if e != 0 { |
||||||
|
err = errnoErr(e) |
||||||
|
} |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
func Statfs(path string, buf *Statfs_t) (err error) { |
||||||
|
p, err := BytePtrFromString(path) |
||||||
|
if err != nil { |
||||||
|
return err |
||||||
|
} |
||||||
|
_, _, e := Syscall(SYS_STATFS64, uintptr(unsafe.Pointer(p)), unsafe.Sizeof(*buf), uintptr(unsafe.Pointer(buf))) |
||||||
|
use(unsafe.Pointer(p)) |
||||||
|
if e != 0 { |
||||||
|
err = errnoErr(e) |
||||||
|
} |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
func Seek(fd int, offset int64, whence int) (off int64, err error) { |
||||||
|
_, _, e := Syscall6(SYS__LLSEEK, uintptr(fd), uintptr(offset>>32), uintptr(offset), uintptr(unsafe.Pointer(&off)), uintptr(whence), 0) |
||||||
|
if e != 0 { |
||||||
|
err = errnoErr(e) |
||||||
|
} |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) } |
||||||
|
|
||||||
|
func NsecToTimespec(nsec int64) (ts Timespec) { |
||||||
|
ts.Sec = int32(nsec / 1e9) |
||||||
|
ts.Nsec = int32(nsec % 1e9) |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
func NsecToTimeval(nsec int64) (tv Timeval) { |
||||||
|
nsec += 999 // round up to microsecond
|
||||||
|
tv.Sec = int32(nsec / 1e9) |
||||||
|
tv.Usec = int32(nsec % 1e9 / 1e3) |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
//sysnb pipe2(p *[2]_C_int, flags int) (err error)
|
||||||
|
|
||||||
|
func Pipe2(p []int, flags int) (err error) { |
||||||
|
if len(p) != 2 { |
||||||
|
return EINVAL |
||||||
|
} |
||||||
|
var pp [2]_C_int |
||||||
|
err = pipe2(&pp, flags) |
||||||
|
p[0] = int(pp[0]) |
||||||
|
p[1] = int(pp[1]) |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
func Pipe(p []int) (err error) { |
||||||
|
if len(p) != 2 { |
||||||
|
return EINVAL |
||||||
|
} |
||||||
|
var pp [2]_C_int |
||||||
|
err = pipe2(&pp, 0) |
||||||
|
p[0] = int(pp[0]) |
||||||
|
p[1] = int(pp[1]) |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
//sys mmap2(addr uintptr, length uintptr, prot int, flags int, fd int, pageOffset uintptr) (xaddr uintptr, err error)
|
||||||
|
|
||||||
|
func mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error) { |
||||||
|
page := uintptr(offset / 4096) |
||||||
|
if offset != int64(page)*4096 { |
||||||
|
return 0, EINVAL |
||||||
|
} |
||||||
|
return mmap2(addr, length, prot, flags, fd, page) |
||||||
|
} |
||||||
|
|
||||||
|
const rlimInf32 = ^uint32(0) |
||||||
|
const rlimInf64 = ^uint64(0) |
||||||
|
|
||||||
|
type rlimit32 struct { |
||||||
|
Cur uint32 |
||||||
|
Max uint32 |
||||||
|
} |
||||||
|
|
||||||
|
//sysnb getrlimit(resource int, rlim *rlimit32) (err error) = SYS_GETRLIMIT
|
||||||
|
|
||||||
|
func Getrlimit(resource int, rlim *Rlimit) (err error) { |
||||||
|
err = prlimit(0, resource, nil, rlim) |
||||||
|
if err != ENOSYS { |
||||||
|
return err |
||||||
|
} |
||||||
|
|
||||||
|
rl := rlimit32{} |
||||||
|
err = getrlimit(resource, &rl) |
||||||
|
if err != nil { |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
if rl.Cur == rlimInf32 { |
||||||
|
rlim.Cur = rlimInf64 |
||||||
|
} else { |
||||||
|
rlim.Cur = uint64(rl.Cur) |
||||||
|
} |
||||||
|
|
||||||
|
if rl.Max == rlimInf32 { |
||||||
|
rlim.Max = rlimInf64 |
||||||
|
} else { |
||||||
|
rlim.Max = uint64(rl.Max) |
||||||
|
} |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
//sysnb setrlimit(resource int, rlim *rlimit32) (err error) = SYS_SETRLIMIT
|
||||||
|
|
||||||
|
func Setrlimit(resource int, rlim *Rlimit) (err error) { |
||||||
|
err = prlimit(0, resource, rlim, nil) |
||||||
|
if err != ENOSYS { |
||||||
|
return err |
||||||
|
} |
||||||
|
|
||||||
|
rl := rlimit32{} |
||||||
|
if rlim.Cur == rlimInf64 { |
||||||
|
rl.Cur = rlimInf32 |
||||||
|
} else if rlim.Cur < uint64(rlimInf32) { |
||||||
|
rl.Cur = uint32(rlim.Cur) |
||||||
|
} else { |
||||||
|
return EINVAL |
||||||
|
} |
||||||
|
if rlim.Max == rlimInf64 { |
||||||
|
rl.Max = rlimInf32 |
||||||
|
} else if rlim.Max < uint64(rlimInf32) { |
||||||
|
rl.Max = uint32(rlim.Max) |
||||||
|
} else { |
||||||
|
return EINVAL |
||||||
|
} |
||||||
|
|
||||||
|
return setrlimit(resource, &rl) |
||||||
|
} |
||||||
|
|
||||||
|
func (r *PtraceRegs) PC() uint64 { return uint64(r.Regs[64]) } |
||||||
|
|
||||||
|
func (r *PtraceRegs) SetPC(pc uint64) { r.Regs[64] = uint32(pc) } |
||||||
|
|
||||||
|
func (iov *Iovec) SetLen(length int) { |
||||||
|
iov.Len = uint32(length) |
||||||
|
} |
||||||
|
|
||||||
|
func (msghdr *Msghdr) SetControllen(length int) { |
||||||
|
msghdr.Controllen = uint32(length) |
||||||
|
} |
||||||
|
|
||||||
|
func (cmsg *Cmsghdr) SetLen(length int) { |
||||||
|
cmsg.Len = uint32(length) |
||||||
|
} |
||||||
|
|
||||||
|
//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error)
|
||||||
|
|
||||||
|
func Poll(fds []PollFd, timeout int) (n int, err error) { |
||||||
|
if len(fds) == 0 { |
||||||
|
return poll(nil, 0, timeout) |
||||||
|
} |
||||||
|
return poll(&fds[0], len(fds), timeout) |
||||||
|
} |
||||||
|
|
||||||
|
func Getpagesize() int { return 4096 } |
@ -0,0 +1,15 @@ |
|||||||
|
// Copyright 2016 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build darwin dragonfly freebsd linux netbsd openbsd solaris
|
||||||
|
// +build !gccgo
|
||||||
|
|
||||||
|
package unix |
||||||
|
|
||||||
|
import "syscall" |
||||||
|
|
||||||
|
func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) |
||||||
|
func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err syscall.Errno) |
||||||
|
func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) |
||||||
|
func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err syscall.Errno) |
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,359 @@ |
|||||||
|
// mksysnum_linux.pl /usr/include/mips-linux-gnu/asm/unistd.h
|
||||||
|
// MACHINE GENERATED BY THE ABOVE COMMAND; DO NOT EDIT
|
||||||
|
|
||||||
|
// +build mips,linux
|
||||||
|
|
||||||
|
package unix |
||||||
|
|
||||||
|
const ( |
||||||
|
SYS_SYSCALL = 4000 |
||||||
|
SYS_EXIT = 4001 |
||||||
|
SYS_FORK = 4002 |
||||||
|
SYS_READ = 4003 |
||||||
|
SYS_WRITE = 4004 |
||||||
|
SYS_OPEN = 4005 |
||||||
|
SYS_CLOSE = 4006 |
||||||
|
SYS_WAITPID = 4007 |
||||||
|
SYS_CREAT = 4008 |
||||||
|
SYS_LINK = 4009 |
||||||
|
SYS_UNLINK = 4010 |
||||||
|
SYS_EXECVE = 4011 |
||||||
|
SYS_CHDIR = 4012 |
||||||
|
SYS_TIME = 4013 |
||||||
|
SYS_MKNOD = 4014 |
||||||
|
SYS_CHMOD = 4015 |
||||||
|
SYS_LCHOWN = 4016 |
||||||
|
SYS_BREAK = 4017 |
||||||
|
SYS_UNUSED18 = 4018 |
||||||
|
SYS_LSEEK = 4019 |
||||||
|
SYS_GETPID = 4020 |
||||||
|
SYS_MOUNT = 4021 |
||||||
|
SYS_UMOUNT = 4022 |
||||||
|
SYS_SETUID = 4023 |
||||||
|
SYS_GETUID = 4024 |
||||||
|
SYS_STIME = 4025 |
||||||
|
SYS_PTRACE = 4026 |
||||||
|
SYS_ALARM = 4027 |
||||||
|
SYS_UNUSED28 = 4028 |
||||||
|
SYS_PAUSE = 4029 |
||||||
|
SYS_UTIME = 4030 |
||||||
|
SYS_STTY = 4031 |
||||||
|
SYS_GTTY = 4032 |
||||||
|
SYS_ACCESS = 4033 |
||||||
|
SYS_NICE = 4034 |
||||||
|
SYS_FTIME = 4035 |
||||||
|
SYS_SYNC = 4036 |
||||||
|
SYS_KILL = 4037 |
||||||
|
SYS_RENAME = 4038 |
||||||
|
SYS_MKDIR = 4039 |
||||||
|
SYS_RMDIR = 4040 |
||||||
|
SYS_DUP = 4041 |
||||||
|
SYS_PIPE = 4042 |
||||||
|
SYS_TIMES = 4043 |
||||||
|
SYS_PROF = 4044 |
||||||
|
SYS_BRK = 4045 |
||||||
|
SYS_SETGID = 4046 |
||||||
|
SYS_GETGID = 4047 |
||||||
|
SYS_SIGNAL = 4048 |
||||||
|
SYS_GETEUID = 4049 |
||||||
|
SYS_GETEGID = 4050 |
||||||
|
SYS_ACCT = 4051 |
||||||
|
SYS_UMOUNT2 = 4052 |
||||||
|
SYS_LOCK = 4053 |
||||||
|
SYS_IOCTL = 4054 |
||||||
|
SYS_FCNTL = 4055 |
||||||
|
SYS_MPX = 4056 |
||||||
|
SYS_SETPGID = 4057 |
||||||
|
SYS_ULIMIT = 4058 |
||||||
|
SYS_UNUSED59 = 4059 |
||||||
|
SYS_UMASK = 4060 |
||||||
|
SYS_CHROOT = 4061 |
||||||
|
SYS_USTAT = 4062 |
||||||
|
SYS_DUP2 = 4063 |
||||||
|
SYS_GETPPID = 4064 |
||||||
|
SYS_GETPGRP = 4065 |
||||||
|
SYS_SETSID = 4066 |
||||||
|
SYS_SIGACTION = 4067 |
||||||
|
SYS_SGETMASK = 4068 |
||||||
|
SYS_SSETMASK = 4069 |
||||||
|
SYS_SETREUID = 4070 |
||||||
|
SYS_SETREGID = 4071 |
||||||
|
SYS_SIGSUSPEND = 4072 |
||||||
|
SYS_SIGPENDING = 4073 |
||||||
|
SYS_SETHOSTNAME = 4074 |
||||||
|
SYS_SETRLIMIT = 4075 |
||||||
|
SYS_GETRLIMIT = 4076 |
||||||
|
SYS_GETRUSAGE = 4077 |
||||||
|
SYS_GETTIMEOFDAY = 4078 |
||||||
|
SYS_SETTIMEOFDAY = 4079 |
||||||
|
SYS_GETGROUPS = 4080 |
||||||
|
SYS_SETGROUPS = 4081 |
||||||
|
SYS_RESERVED82 = 4082 |
||||||
|
SYS_SYMLINK = 4083 |
||||||
|
SYS_UNUSED84 = 4084 |
||||||
|
SYS_READLINK = 4085 |
||||||
|
SYS_USELIB = 4086 |
||||||
|
SYS_SWAPON = 4087 |
||||||
|
SYS_REBOOT = 4088 |
||||||
|
SYS_READDIR = 4089 |
||||||
|
SYS_MMAP = 4090 |
||||||
|
SYS_MUNMAP = 4091 |
||||||
|
SYS_TRUNCATE = 4092 |
||||||
|
SYS_FTRUNCATE = 4093 |
||||||
|
SYS_FCHMOD = 4094 |
||||||
|
SYS_FCHOWN = 4095 |
||||||
|
SYS_GETPRIORITY = 4096 |
||||||
|
SYS_SETPRIORITY = 4097 |
||||||
|
SYS_PROFIL = 4098 |
||||||
|
SYS_STATFS = 4099 |
||||||
|
SYS_FSTATFS = 4100 |
||||||
|
SYS_IOPERM = 4101 |
||||||
|
SYS_SOCKETCALL = 4102 |
||||||
|
SYS_SYSLOG = 4103 |
||||||
|
SYS_SETITIMER = 4104 |
||||||
|
SYS_GETITIMER = 4105 |
||||||
|
SYS_STAT = 4106 |
||||||
|
SYS_LSTAT = 4107 |
||||||
|
SYS_FSTAT = 4108 |
||||||
|
SYS_UNUSED109 = 4109 |
||||||
|
SYS_IOPL = 4110 |
||||||
|
SYS_VHANGUP = 4111 |
||||||
|
SYS_IDLE = 4112 |
||||||
|
SYS_VM86 = 4113 |
||||||
|
SYS_WAIT4 = 4114 |
||||||
|
SYS_SWAPOFF = 4115 |
||||||
|
SYS_SYSINFO = 4116 |
||||||
|
SYS_IPC = 4117 |
||||||
|
SYS_FSYNC = 4118 |
||||||
|
SYS_SIGRETURN = 4119 |
||||||
|
SYS_CLONE = 4120 |
||||||
|
SYS_SETDOMAINNAME = 4121 |
||||||
|
SYS_UNAME = 4122 |
||||||
|
SYS_MODIFY_LDT = 4123 |
||||||
|
SYS_ADJTIMEX = 4124 |
||||||
|
SYS_MPROTECT = 4125 |
||||||
|
SYS_SIGPROCMASK = 4126 |
||||||
|
SYS_CREATE_MODULE = 4127 |
||||||
|
SYS_INIT_MODULE = 4128 |
||||||
|
SYS_DELETE_MODULE = 4129 |
||||||
|
SYS_GET_KERNEL_SYMS = 4130 |
||||||
|
SYS_QUOTACTL = 4131 |
||||||
|
SYS_GETPGID = 4132 |
||||||
|
SYS_FCHDIR = 4133 |
||||||
|
SYS_BDFLUSH = 4134 |
||||||
|
SYS_SYSFS = 4135 |
||||||
|
SYS_PERSONALITY = 4136 |
||||||
|
SYS_AFS_SYSCALL = 4137 |
||||||
|
SYS_SETFSUID = 4138 |
||||||
|
SYS_SETFSGID = 4139 |
||||||
|
SYS__LLSEEK = 4140 |
||||||
|
SYS_GETDENTS = 4141 |
||||||
|
SYS__NEWSELECT = 4142 |
||||||
|
SYS_FLOCK = 4143 |
||||||
|
SYS_MSYNC = 4144 |
||||||
|
SYS_READV = 4145 |
||||||
|
SYS_WRITEV = 4146 |
||||||
|
SYS_CACHEFLUSH = 4147 |
||||||
|
SYS_CACHECTL = 4148 |
||||||
|
SYS_SYSMIPS = 4149 |
||||||
|
SYS_UNUSED150 = 4150 |
||||||
|
SYS_GETSID = 4151 |
||||||
|
SYS_FDATASYNC = 4152 |
||||||
|
SYS__SYSCTL = 4153 |
||||||
|
SYS_MLOCK = 4154 |
||||||
|
SYS_MUNLOCK = 4155 |
||||||
|
SYS_MLOCKALL = 4156 |
||||||
|
SYS_MUNLOCKALL = 4157 |
||||||
|
SYS_SCHED_SETPARAM = 4158 |
||||||
|
SYS_SCHED_GETPARAM = 4159 |
||||||
|
SYS_SCHED_SETSCHEDULER = 4160 |
||||||
|
SYS_SCHED_GETSCHEDULER = 4161 |
||||||
|
SYS_SCHED_YIELD = 4162 |
||||||
|
SYS_SCHED_GET_PRIORITY_MAX = 4163 |
||||||
|
SYS_SCHED_GET_PRIORITY_MIN = 4164 |
||||||
|
SYS_SCHED_RR_GET_INTERVAL = 4165 |
||||||
|
SYS_NANOSLEEP = 4166 |
||||||
|
SYS_MREMAP = 4167 |
||||||
|
SYS_ACCEPT = 4168 |
||||||
|
SYS_BIND = 4169 |
||||||
|
SYS_CONNECT = 4170 |
||||||
|
SYS_GETPEERNAME = 4171 |
||||||
|
SYS_GETSOCKNAME = 4172 |
||||||
|
SYS_GETSOCKOPT = 4173 |
||||||
|
SYS_LISTEN = 4174 |
||||||
|
SYS_RECV = 4175 |
||||||
|
SYS_RECVFROM = 4176 |
||||||
|
SYS_RECVMSG = 4177 |
||||||
|
SYS_SEND = 4178 |
||||||
|
SYS_SENDMSG = 4179 |
||||||
|
SYS_SENDTO = 4180 |
||||||
|
SYS_SETSOCKOPT = 4181 |
||||||
|
SYS_SHUTDOWN = 4182 |
||||||
|
SYS_SOCKET = 4183 |
||||||
|
SYS_SOCKETPAIR = 4184 |
||||||
|
SYS_SETRESUID = 4185 |
||||||
|
SYS_GETRESUID = 4186 |
||||||
|
SYS_QUERY_MODULE = 4187 |
||||||
|
SYS_POLL = 4188 |
||||||
|
SYS_NFSSERVCTL = 4189 |
||||||
|
SYS_SETRESGID = 4190 |
||||||
|
SYS_GETRESGID = 4191 |
||||||
|
SYS_PRCTL = 4192 |
||||||
|
SYS_RT_SIGRETURN = 4193 |
||||||
|
SYS_RT_SIGACTION = 4194 |
||||||
|
SYS_RT_SIGPROCMASK = 4195 |
||||||
|
SYS_RT_SIGPENDING = 4196 |
||||||
|
SYS_RT_SIGTIMEDWAIT = 4197 |
||||||
|
SYS_RT_SIGQUEUEINFO = 4198 |
||||||
|
SYS_RT_SIGSUSPEND = 4199 |
||||||
|
SYS_PREAD64 = 4200 |
||||||
|
SYS_PWRITE64 = 4201 |
||||||
|
SYS_CHOWN = 4202 |
||||||
|
SYS_GETCWD = 4203 |
||||||
|
SYS_CAPGET = 4204 |
||||||
|
SYS_CAPSET = 4205 |
||||||
|
SYS_SIGALTSTACK = 4206 |
||||||
|
SYS_SENDFILE = 4207 |
||||||
|
SYS_GETPMSG = 4208 |
||||||
|
SYS_PUTPMSG = 4209 |
||||||
|
SYS_MMAP2 = 4210 |
||||||
|
SYS_TRUNCATE64 = 4211 |
||||||
|
SYS_FTRUNCATE64 = 4212 |
||||||
|
SYS_STAT64 = 4213 |
||||||
|
SYS_LSTAT64 = 4214 |
||||||
|
SYS_FSTAT64 = 4215 |
||||||
|
SYS_PIVOT_ROOT = 4216 |
||||||
|
SYS_MINCORE = 4217 |
||||||
|
SYS_MADVISE = 4218 |
||||||
|
SYS_GETDENTS64 = 4219 |
||||||
|
SYS_FCNTL64 = 4220 |
||||||
|
SYS_RESERVED221 = 4221 |
||||||
|
SYS_GETTID = 4222 |
||||||
|
SYS_READAHEAD = 4223 |
||||||
|
SYS_SETXATTR = 4224 |
||||||
|
SYS_LSETXATTR = 4225 |
||||||
|
SYS_FSETXATTR = 4226 |
||||||
|
SYS_GETXATTR = 4227 |
||||||
|
SYS_LGETXATTR = 4228 |
||||||
|
SYS_FGETXATTR = 4229 |
||||||
|
SYS_LISTXATTR = 4230 |
||||||
|
SYS_LLISTXATTR = 4231 |
||||||
|
SYS_FLISTXATTR = 4232 |
||||||
|
SYS_REMOVEXATTR = 4233 |
||||||
|
SYS_LREMOVEXATTR = 4234 |
||||||
|
SYS_FREMOVEXATTR = 4235 |
||||||
|
SYS_TKILL = 4236 |
||||||
|
SYS_SENDFILE64 = 4237 |
||||||
|
SYS_FUTEX = 4238 |
||||||
|
SYS_SCHED_SETAFFINITY = 4239 |
||||||
|
SYS_SCHED_GETAFFINITY = 4240 |
||||||
|
SYS_IO_SETUP = 4241 |
||||||
|
SYS_IO_DESTROY = 4242 |
||||||
|
SYS_IO_GETEVENTS = 4243 |
||||||
|
SYS_IO_SUBMIT = 4244 |
||||||
|
SYS_IO_CANCEL = 4245 |
||||||
|
SYS_EXIT_GROUP = 4246 |
||||||
|
SYS_LOOKUP_DCOOKIE = 4247 |
||||||
|
SYS_EPOLL_CREATE = 4248 |
||||||
|
SYS_EPOLL_CTL = 4249 |
||||||
|
SYS_EPOLL_WAIT = 4250 |
||||||
|
SYS_REMAP_FILE_PAGES = 4251 |
||||||
|
SYS_SET_TID_ADDRESS = 4252 |
||||||
|
SYS_RESTART_SYSCALL = 4253 |
||||||
|
SYS_FADVISE64 = 4254 |
||||||
|
SYS_STATFS64 = 4255 |
||||||
|
SYS_FSTATFS64 = 4256 |
||||||
|
SYS_TIMER_CREATE = 4257 |
||||||
|
SYS_TIMER_SETTIME = 4258 |
||||||
|
SYS_TIMER_GETTIME = 4259 |
||||||
|
SYS_TIMER_GETOVERRUN = 4260 |
||||||
|
SYS_TIMER_DELETE = 4261 |
||||||
|
SYS_CLOCK_SETTIME = 4262 |
||||||
|
SYS_CLOCK_GETTIME = 4263 |
||||||
|
SYS_CLOCK_GETRES = 4264 |
||||||
|
SYS_CLOCK_NANOSLEEP = 4265 |
||||||
|
SYS_TGKILL = 4266 |
||||||
|
SYS_UTIMES = 4267 |
||||||
|
SYS_MBIND = 4268 |
||||||
|
SYS_GET_MEMPOLICY = 4269 |
||||||
|
SYS_SET_MEMPOLICY = 4270 |
||||||
|
SYS_MQ_OPEN = 4271 |
||||||
|
SYS_MQ_UNLINK = 4272 |
||||||
|
SYS_MQ_TIMEDSEND = 4273 |
||||||
|
SYS_MQ_TIMEDRECEIVE = 4274 |
||||||
|
SYS_MQ_NOTIFY = 4275 |
||||||
|
SYS_MQ_GETSETATTR = 4276 |
||||||
|
SYS_VSERVER = 4277 |
||||||
|
SYS_WAITID = 4278 |
||||||
|
SYS_ADD_KEY = 4280 |
||||||
|
SYS_REQUEST_KEY = 4281 |
||||||
|
SYS_KEYCTL = 4282 |
||||||
|
SYS_SET_THREAD_AREA = 4283 |
||||||
|
SYS_INOTIFY_INIT = 4284 |
||||||
|
SYS_INOTIFY_ADD_WATCH = 4285 |
||||||
|
SYS_INOTIFY_RM_WATCH = 4286 |
||||||
|
SYS_MIGRATE_PAGES = 4287 |
||||||
|
SYS_OPENAT = 4288 |
||||||
|
SYS_MKDIRAT = 4289 |
||||||
|
SYS_MKNODAT = 4290 |
||||||
|
SYS_FCHOWNAT = 4291 |
||||||
|
SYS_FUTIMESAT = 4292 |
||||||
|
SYS_FSTATAT64 = 4293 |
||||||
|
SYS_UNLINKAT = 4294 |
||||||
|
SYS_RENAMEAT = 4295 |
||||||
|
SYS_LINKAT = 4296 |
||||||
|
SYS_SYMLINKAT = 4297 |
||||||
|
SYS_READLINKAT = 4298 |
||||||
|
SYS_FCHMODAT = 4299 |
||||||
|
SYS_FACCESSAT = 4300 |
||||||
|
SYS_PSELECT6 = 4301 |
||||||
|
SYS_PPOLL = 4302 |
||||||
|
SYS_UNSHARE = 4303 |
||||||
|
SYS_SPLICE = 4304 |
||||||
|
SYS_SYNC_FILE_RANGE = 4305 |
||||||
|
SYS_TEE = 4306 |
||||||
|
SYS_VMSPLICE = 4307 |
||||||
|
SYS_MOVE_PAGES = 4308 |
||||||
|
SYS_SET_ROBUST_LIST = 4309 |
||||||
|
SYS_GET_ROBUST_LIST = 4310 |
||||||
|
SYS_KEXEC_LOAD = 4311 |
||||||
|
SYS_GETCPU = 4312 |
||||||
|
SYS_EPOLL_PWAIT = 4313 |
||||||
|
SYS_IOPRIO_SET = 4314 |
||||||
|
SYS_IOPRIO_GET = 4315 |
||||||
|
SYS_UTIMENSAT = 4316 |
||||||
|
SYS_SIGNALFD = 4317 |
||||||
|
SYS_TIMERFD = 4318 |
||||||
|
SYS_EVENTFD = 4319 |
||||||
|
SYS_FALLOCATE = 4320 |
||||||
|
SYS_TIMERFD_CREATE = 4321 |
||||||
|
SYS_TIMERFD_GETTIME = 4322 |
||||||
|
SYS_TIMERFD_SETTIME = 4323 |
||||||
|
SYS_SIGNALFD4 = 4324 |
||||||
|
SYS_EVENTFD2 = 4325 |
||||||
|
SYS_EPOLL_CREATE1 = 4326 |
||||||
|
SYS_DUP3 = 4327 |
||||||
|
SYS_PIPE2 = 4328 |
||||||
|
SYS_INOTIFY_INIT1 = 4329 |
||||||
|
SYS_PREADV = 4330 |
||||||
|
SYS_PWRITEV = 4331 |
||||||
|
SYS_RT_TGSIGQUEUEINFO = 4332 |
||||||
|
SYS_PERF_EVENT_OPEN = 4333 |
||||||
|
SYS_ACCEPT4 = 4334 |
||||||
|
SYS_RECVMMSG = 4335 |
||||||
|
SYS_FANOTIFY_INIT = 4336 |
||||||
|
SYS_FANOTIFY_MARK = 4337 |
||||||
|
SYS_PRLIMIT64 = 4338 |
||||||
|
SYS_NAME_TO_HANDLE_AT = 4339 |
||||||
|
SYS_OPEN_BY_HANDLE_AT = 4340 |
||||||
|
SYS_CLOCK_ADJTIME = 4341 |
||||||
|
SYS_SYNCFS = 4342 |
||||||
|
SYS_SENDMMSG = 4343 |
||||||
|
SYS_SETNS = 4344 |
||||||
|
SYS_PROCESS_VM_READV = 4345 |
||||||
|
SYS_PROCESS_VM_WRITEV = 4346 |
||||||
|
SYS_LINUX_SYSCALLS = 4346 |
||||||
|
SYS_O32_LINUX_SYSCALLS = 4346 |
||||||
|
SYS_64_LINUX_SYSCALLS = 4305 |
||||||
|
SYS_N32_LINUX_SYSCALLS = 4310 |
||||||
|
) |
@ -0,0 +1,359 @@ |
|||||||
|
// mksysnum_linux.pl /usr/include/mips-linux-gnu/asm/unistd.h
|
||||||
|
// MACHINE GENERATED BY THE ABOVE COMMAND; DO NOT EDIT
|
||||||
|
|
||||||
|
// +build mipsle,linux
|
||||||
|
|
||||||
|
package unix |
||||||
|
|
||||||
|
const ( |
||||||
|
SYS_SYSCALL = 4000 |
||||||
|
SYS_EXIT = 4001 |
||||||
|
SYS_FORK = 4002 |
||||||
|
SYS_READ = 4003 |
||||||
|
SYS_WRITE = 4004 |
||||||
|
SYS_OPEN = 4005 |
||||||
|
SYS_CLOSE = 4006 |
||||||
|
SYS_WAITPID = 4007 |
||||||
|
SYS_CREAT = 4008 |
||||||
|
SYS_LINK = 4009 |
||||||
|
SYS_UNLINK = 4010 |
||||||
|
SYS_EXECVE = 4011 |
||||||
|
SYS_CHDIR = 4012 |
||||||
|
SYS_TIME = 4013 |
||||||
|
SYS_MKNOD = 4014 |
||||||
|
SYS_CHMOD = 4015 |
||||||
|
SYS_LCHOWN = 4016 |
||||||
|
SYS_BREAK = 4017 |
||||||
|
SYS_UNUSED18 = 4018 |
||||||
|
SYS_LSEEK = 4019 |
||||||
|
SYS_GETPID = 4020 |
||||||
|
SYS_MOUNT = 4021 |
||||||
|
SYS_UMOUNT = 4022 |
||||||
|
SYS_SETUID = 4023 |
||||||
|
SYS_GETUID = 4024 |
||||||
|
SYS_STIME = 4025 |
||||||
|
SYS_PTRACE = 4026 |
||||||
|
SYS_ALARM = 4027 |
||||||
|
SYS_UNUSED28 = 4028 |
||||||
|
SYS_PAUSE = 4029 |
||||||
|
SYS_UTIME = 4030 |
||||||
|
SYS_STTY = 4031 |
||||||
|
SYS_GTTY = 4032 |
||||||
|
SYS_ACCESS = 4033 |
||||||
|
SYS_NICE = 4034 |
||||||
|
SYS_FTIME = 4035 |
||||||
|
SYS_SYNC = 4036 |
||||||
|
SYS_KILL = 4037 |
||||||
|
SYS_RENAME = 4038 |
||||||
|
SYS_MKDIR = 4039 |
||||||
|
SYS_RMDIR = 4040 |
||||||
|
SYS_DUP = 4041 |
||||||
|
SYS_PIPE = 4042 |
||||||
|
SYS_TIMES = 4043 |
||||||
|
SYS_PROF = 4044 |
||||||
|
SYS_BRK = 4045 |
||||||
|
SYS_SETGID = 4046 |
||||||
|
SYS_GETGID = 4047 |
||||||
|
SYS_SIGNAL = 4048 |
||||||
|
SYS_GETEUID = 4049 |
||||||
|
SYS_GETEGID = 4050 |
||||||
|
SYS_ACCT = 4051 |
||||||
|
SYS_UMOUNT2 = 4052 |
||||||
|
SYS_LOCK = 4053 |
||||||
|
SYS_IOCTL = 4054 |
||||||
|
SYS_FCNTL = 4055 |
||||||
|
SYS_MPX = 4056 |
||||||
|
SYS_SETPGID = 4057 |
||||||
|
SYS_ULIMIT = 4058 |
||||||
|
SYS_UNUSED59 = 4059 |
||||||
|
SYS_UMASK = 4060 |
||||||
|
SYS_CHROOT = 4061 |
||||||
|
SYS_USTAT = 4062 |
||||||
|
SYS_DUP2 = 4063 |
||||||
|
SYS_GETPPID = 4064 |
||||||
|
SYS_GETPGRP = 4065 |
||||||
|
SYS_SETSID = 4066 |
||||||
|
SYS_SIGACTION = 4067 |
||||||
|
SYS_SGETMASK = 4068 |
||||||
|
SYS_SSETMASK = 4069 |
||||||
|
SYS_SETREUID = 4070 |
||||||
|
SYS_SETREGID = 4071 |
||||||
|
SYS_SIGSUSPEND = 4072 |
||||||
|
SYS_SIGPENDING = 4073 |
||||||
|
SYS_SETHOSTNAME = 4074 |
||||||
|
SYS_SETRLIMIT = 4075 |
||||||
|
SYS_GETRLIMIT = 4076 |
||||||
|
SYS_GETRUSAGE = 4077 |
||||||
|
SYS_GETTIMEOFDAY = 4078 |
||||||
|
SYS_SETTIMEOFDAY = 4079 |
||||||
|
SYS_GETGROUPS = 4080 |
||||||
|
SYS_SETGROUPS = 4081 |
||||||
|
SYS_RESERVED82 = 4082 |
||||||
|
SYS_SYMLINK = 4083 |
||||||
|
SYS_UNUSED84 = 4084 |
||||||
|
SYS_READLINK = 4085 |
||||||
|
SYS_USELIB = 4086 |
||||||
|
SYS_SWAPON = 4087 |
||||||
|
SYS_REBOOT = 4088 |
||||||
|
SYS_READDIR = 4089 |
||||||
|
SYS_MMAP = 4090 |
||||||
|
SYS_MUNMAP = 4091 |
||||||
|
SYS_TRUNCATE = 4092 |
||||||
|
SYS_FTRUNCATE = 4093 |
||||||
|
SYS_FCHMOD = 4094 |
||||||
|
SYS_FCHOWN = 4095 |
||||||
|
SYS_GETPRIORITY = 4096 |
||||||
|
SYS_SETPRIORITY = 4097 |
||||||
|
SYS_PROFIL = 4098 |
||||||
|
SYS_STATFS = 4099 |
||||||
|
SYS_FSTATFS = 4100 |
||||||
|
SYS_IOPERM = 4101 |
||||||
|
SYS_SOCKETCALL = 4102 |
||||||
|
SYS_SYSLOG = 4103 |
||||||
|
SYS_SETITIMER = 4104 |
||||||
|
SYS_GETITIMER = 4105 |
||||||
|
SYS_STAT = 4106 |
||||||
|
SYS_LSTAT = 4107 |
||||||
|
SYS_FSTAT = 4108 |
||||||
|
SYS_UNUSED109 = 4109 |
||||||
|
SYS_IOPL = 4110 |
||||||
|
SYS_VHANGUP = 4111 |
||||||
|
SYS_IDLE = 4112 |
||||||
|
SYS_VM86 = 4113 |
||||||
|
SYS_WAIT4 = 4114 |
||||||
|
SYS_SWAPOFF = 4115 |
||||||
|
SYS_SYSINFO = 4116 |
||||||
|
SYS_IPC = 4117 |
||||||
|
SYS_FSYNC = 4118 |
||||||
|
SYS_SIGRETURN = 4119 |
||||||
|
SYS_CLONE = 4120 |
||||||
|
SYS_SETDOMAINNAME = 4121 |
||||||
|
SYS_UNAME = 4122 |
||||||
|
SYS_MODIFY_LDT = 4123 |
||||||
|
SYS_ADJTIMEX = 4124 |
||||||
|
SYS_MPROTECT = 4125 |
||||||
|
SYS_SIGPROCMASK = 4126 |
||||||
|
SYS_CREATE_MODULE = 4127 |
||||||
|
SYS_INIT_MODULE = 4128 |
||||||
|
SYS_DELETE_MODULE = 4129 |
||||||
|
SYS_GET_KERNEL_SYMS = 4130 |
||||||
|
SYS_QUOTACTL = 4131 |
||||||
|
SYS_GETPGID = 4132 |
||||||
|
SYS_FCHDIR = 4133 |
||||||
|
SYS_BDFLUSH = 4134 |
||||||
|
SYS_SYSFS = 4135 |
||||||
|
SYS_PERSONALITY = 4136 |
||||||
|
SYS_AFS_SYSCALL = 4137 |
||||||
|
SYS_SETFSUID = 4138 |
||||||
|
SYS_SETFSGID = 4139 |
||||||
|
SYS__LLSEEK = 4140 |
||||||
|
SYS_GETDENTS = 4141 |
||||||
|
SYS__NEWSELECT = 4142 |
||||||
|
SYS_FLOCK = 4143 |
||||||
|
SYS_MSYNC = 4144 |
||||||
|
SYS_READV = 4145 |
||||||
|
SYS_WRITEV = 4146 |
||||||
|
SYS_CACHEFLUSH = 4147 |
||||||
|
SYS_CACHECTL = 4148 |
||||||
|
SYS_SYSMIPS = 4149 |
||||||
|
SYS_UNUSED150 = 4150 |
||||||
|
SYS_GETSID = 4151 |
||||||
|
SYS_FDATASYNC = 4152 |
||||||
|
SYS__SYSCTL = 4153 |
||||||
|
SYS_MLOCK = 4154 |
||||||
|
SYS_MUNLOCK = 4155 |
||||||
|
SYS_MLOCKALL = 4156 |
||||||
|
SYS_MUNLOCKALL = 4157 |
||||||
|
SYS_SCHED_SETPARAM = 4158 |
||||||
|
SYS_SCHED_GETPARAM = 4159 |
||||||
|
SYS_SCHED_SETSCHEDULER = 4160 |
||||||
|
SYS_SCHED_GETSCHEDULER = 4161 |
||||||
|
SYS_SCHED_YIELD = 4162 |
||||||
|
SYS_SCHED_GET_PRIORITY_MAX = 4163 |
||||||
|
SYS_SCHED_GET_PRIORITY_MIN = 4164 |
||||||
|
SYS_SCHED_RR_GET_INTERVAL = 4165 |
||||||
|
SYS_NANOSLEEP = 4166 |
||||||
|
SYS_MREMAP = 4167 |
||||||
|
SYS_ACCEPT = 4168 |
||||||
|
SYS_BIND = 4169 |
||||||
|
SYS_CONNECT = 4170 |
||||||
|
SYS_GETPEERNAME = 4171 |
||||||
|
SYS_GETSOCKNAME = 4172 |
||||||
|
SYS_GETSOCKOPT = 4173 |
||||||
|
SYS_LISTEN = 4174 |
||||||
|
SYS_RECV = 4175 |
||||||
|
SYS_RECVFROM = 4176 |
||||||
|
SYS_RECVMSG = 4177 |
||||||
|
SYS_SEND = 4178 |
||||||
|
SYS_SENDMSG = 4179 |
||||||
|
SYS_SENDTO = 4180 |
||||||
|
SYS_SETSOCKOPT = 4181 |
||||||
|
SYS_SHUTDOWN = 4182 |
||||||
|
SYS_SOCKET = 4183 |
||||||
|
SYS_SOCKETPAIR = 4184 |
||||||
|
SYS_SETRESUID = 4185 |
||||||
|
SYS_GETRESUID = 4186 |
||||||
|
SYS_QUERY_MODULE = 4187 |
||||||
|
SYS_POLL = 4188 |
||||||
|
SYS_NFSSERVCTL = 4189 |
||||||
|
SYS_SETRESGID = 4190 |
||||||
|
SYS_GETRESGID = 4191 |
||||||
|
SYS_PRCTL = 4192 |
||||||
|
SYS_RT_SIGRETURN = 4193 |
||||||
|
SYS_RT_SIGACTION = 4194 |
||||||
|
SYS_RT_SIGPROCMASK = 4195 |
||||||
|
SYS_RT_SIGPENDING = 4196 |
||||||
|
SYS_RT_SIGTIMEDWAIT = 4197 |
||||||
|
SYS_RT_SIGQUEUEINFO = 4198 |
||||||
|
SYS_RT_SIGSUSPEND = 4199 |
||||||
|
SYS_PREAD64 = 4200 |
||||||
|
SYS_PWRITE64 = 4201 |
||||||
|
SYS_CHOWN = 4202 |
||||||
|
SYS_GETCWD = 4203 |
||||||
|
SYS_CAPGET = 4204 |
||||||
|
SYS_CAPSET = 4205 |
||||||
|
SYS_SIGALTSTACK = 4206 |
||||||
|
SYS_SENDFILE = 4207 |
||||||
|
SYS_GETPMSG = 4208 |
||||||
|
SYS_PUTPMSG = 4209 |
||||||
|
SYS_MMAP2 = 4210 |
||||||
|
SYS_TRUNCATE64 = 4211 |
||||||
|
SYS_FTRUNCATE64 = 4212 |
||||||
|
SYS_STAT64 = 4213 |
||||||
|
SYS_LSTAT64 = 4214 |
||||||
|
SYS_FSTAT64 = 4215 |
||||||
|
SYS_PIVOT_ROOT = 4216 |
||||||
|
SYS_MINCORE = 4217 |
||||||
|
SYS_MADVISE = 4218 |
||||||
|
SYS_GETDENTS64 = 4219 |
||||||
|
SYS_FCNTL64 = 4220 |
||||||
|
SYS_RESERVED221 = 4221 |
||||||
|
SYS_GETTID = 4222 |
||||||
|
SYS_READAHEAD = 4223 |
||||||
|
SYS_SETXATTR = 4224 |
||||||
|
SYS_LSETXATTR = 4225 |
||||||
|
SYS_FSETXATTR = 4226 |
||||||
|
SYS_GETXATTR = 4227 |
||||||
|
SYS_LGETXATTR = 4228 |
||||||
|
SYS_FGETXATTR = 4229 |
||||||
|
SYS_LISTXATTR = 4230 |
||||||
|
SYS_LLISTXATTR = 4231 |
||||||
|
SYS_FLISTXATTR = 4232 |
||||||
|
SYS_REMOVEXATTR = 4233 |
||||||
|
SYS_LREMOVEXATTR = 4234 |
||||||
|
SYS_FREMOVEXATTR = 4235 |
||||||
|
SYS_TKILL = 4236 |
||||||
|
SYS_SENDFILE64 = 4237 |
||||||
|
SYS_FUTEX = 4238 |
||||||
|
SYS_SCHED_SETAFFINITY = 4239 |
||||||
|
SYS_SCHED_GETAFFINITY = 4240 |
||||||
|
SYS_IO_SETUP = 4241 |
||||||
|
SYS_IO_DESTROY = 4242 |
||||||
|
SYS_IO_GETEVENTS = 4243 |
||||||
|
SYS_IO_SUBMIT = 4244 |
||||||
|
SYS_IO_CANCEL = 4245 |
||||||
|
SYS_EXIT_GROUP = 4246 |
||||||
|
SYS_LOOKUP_DCOOKIE = 4247 |
||||||
|
SYS_EPOLL_CREATE = 4248 |
||||||
|
SYS_EPOLL_CTL = 4249 |
||||||
|
SYS_EPOLL_WAIT = 4250 |
||||||
|
SYS_REMAP_FILE_PAGES = 4251 |
||||||
|
SYS_SET_TID_ADDRESS = 4252 |
||||||
|
SYS_RESTART_SYSCALL = 4253 |
||||||
|
SYS_FADVISE64 = 4254 |
||||||
|
SYS_STATFS64 = 4255 |
||||||
|
SYS_FSTATFS64 = 4256 |
||||||
|
SYS_TIMER_CREATE = 4257 |
||||||
|
SYS_TIMER_SETTIME = 4258 |
||||||
|
SYS_TIMER_GETTIME = 4259 |
||||||
|
SYS_TIMER_GETOVERRUN = 4260 |
||||||
|
SYS_TIMER_DELETE = 4261 |
||||||
|
SYS_CLOCK_SETTIME = 4262 |
||||||
|
SYS_CLOCK_GETTIME = 4263 |
||||||
|
SYS_CLOCK_GETRES = 4264 |
||||||
|
SYS_CLOCK_NANOSLEEP = 4265 |
||||||
|
SYS_TGKILL = 4266 |
||||||
|
SYS_UTIMES = 4267 |
||||||
|
SYS_MBIND = 4268 |
||||||
|
SYS_GET_MEMPOLICY = 4269 |
||||||
|
SYS_SET_MEMPOLICY = 4270 |
||||||
|
SYS_MQ_OPEN = 4271 |
||||||
|
SYS_MQ_UNLINK = 4272 |
||||||
|
SYS_MQ_TIMEDSEND = 4273 |
||||||
|
SYS_MQ_TIMEDRECEIVE = 4274 |
||||||
|
SYS_MQ_NOTIFY = 4275 |
||||||
|
SYS_MQ_GETSETATTR = 4276 |
||||||
|
SYS_VSERVER = 4277 |
||||||
|
SYS_WAITID = 4278 |
||||||
|
SYS_ADD_KEY = 4280 |
||||||
|
SYS_REQUEST_KEY = 4281 |
||||||
|
SYS_KEYCTL = 4282 |
||||||
|
SYS_SET_THREAD_AREA = 4283 |
||||||
|
SYS_INOTIFY_INIT = 4284 |
||||||
|
SYS_INOTIFY_ADD_WATCH = 4285 |
||||||
|
SYS_INOTIFY_RM_WATCH = 4286 |
||||||
|
SYS_MIGRATE_PAGES = 4287 |
||||||
|
SYS_OPENAT = 4288 |
||||||
|
SYS_MKDIRAT = 4289 |
||||||
|
SYS_MKNODAT = 4290 |
||||||
|
SYS_FCHOWNAT = 4291 |
||||||
|
SYS_FUTIMESAT = 4292 |
||||||
|
SYS_FSTATAT64 = 4293 |
||||||
|
SYS_UNLINKAT = 4294 |
||||||
|
SYS_RENAMEAT = 4295 |
||||||
|
SYS_LINKAT = 4296 |
||||||
|
SYS_SYMLINKAT = 4297 |
||||||
|
SYS_READLINKAT = 4298 |
||||||
|
SYS_FCHMODAT = 4299 |
||||||
|
SYS_FACCESSAT = 4300 |
||||||
|
SYS_PSELECT6 = 4301 |
||||||
|
SYS_PPOLL = 4302 |
||||||
|
SYS_UNSHARE = 4303 |
||||||
|
SYS_SPLICE = 4304 |
||||||
|
SYS_SYNC_FILE_RANGE = 4305 |
||||||
|
SYS_TEE = 4306 |
||||||
|
SYS_VMSPLICE = 4307 |
||||||
|
SYS_MOVE_PAGES = 4308 |
||||||
|
SYS_SET_ROBUST_LIST = 4309 |
||||||
|
SYS_GET_ROBUST_LIST = 4310 |
||||||
|
SYS_KEXEC_LOAD = 4311 |
||||||
|
SYS_GETCPU = 4312 |
||||||
|
SYS_EPOLL_PWAIT = 4313 |
||||||
|
SYS_IOPRIO_SET = 4314 |
||||||
|
SYS_IOPRIO_GET = 4315 |
||||||
|
SYS_UTIMENSAT = 4316 |
||||||
|
SYS_SIGNALFD = 4317 |
||||||
|
SYS_TIMERFD = 4318 |
||||||
|
SYS_EVENTFD = 4319 |
||||||
|
SYS_FALLOCATE = 4320 |
||||||
|
SYS_TIMERFD_CREATE = 4321 |
||||||
|
SYS_TIMERFD_GETTIME = 4322 |
||||||
|
SYS_TIMERFD_SETTIME = 4323 |
||||||
|
SYS_SIGNALFD4 = 4324 |
||||||
|
SYS_EVENTFD2 = 4325 |
||||||
|
SYS_EPOLL_CREATE1 = 4326 |
||||||
|
SYS_DUP3 = 4327 |
||||||
|
SYS_PIPE2 = 4328 |
||||||
|
SYS_INOTIFY_INIT1 = 4329 |
||||||
|
SYS_PREADV = 4330 |
||||||
|
SYS_PWRITEV = 4331 |
||||||
|
SYS_RT_TGSIGQUEUEINFO = 4332 |
||||||
|
SYS_PERF_EVENT_OPEN = 4333 |
||||||
|
SYS_ACCEPT4 = 4334 |
||||||
|
SYS_RECVMMSG = 4335 |
||||||
|
SYS_FANOTIFY_INIT = 4336 |
||||||
|
SYS_FANOTIFY_MARK = 4337 |
||||||
|
SYS_PRLIMIT64 = 4338 |
||||||
|
SYS_NAME_TO_HANDLE_AT = 4339 |
||||||
|
SYS_OPEN_BY_HANDLE_AT = 4340 |
||||||
|
SYS_CLOCK_ADJTIME = 4341 |
||||||
|
SYS_SYNCFS = 4342 |
||||||
|
SYS_SENDMMSG = 4343 |
||||||
|
SYS_SETNS = 4344 |
||||||
|
SYS_PROCESS_VM_READV = 4345 |
||||||
|
SYS_PROCESS_VM_WRITEV = 4346 |
||||||
|
SYS_LINUX_SYSCALLS = 4346 |
||||||
|
SYS_O32_LINUX_SYSCALLS = 4346 |
||||||
|
SYS_64_LINUX_SYSCALLS = 4305 |
||||||
|
SYS_N32_LINUX_SYSCALLS = 4310 |
||||||
|
) |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue