...

Text file src/github.com/twitchyliquid64/golang-asm/gen.sh

Documentation: github.com/twitchyliquid64/golang-asm

     1#!/bin/bash
     2# Downloads the Go sources, building the assembler into a standalone package.
     3
     4OUT_DIR=$(pwd)
     5BASE_PKG_PATH='github.com/twitchyliquid64/golang-asm'
     6
     7TMP_PATH=$(mktemp -d)
     8cleanup () {
     9  if [[ "${TMP_PATH}" != "" ]]; then
    10    rm -rf "${TMP_PATH}"
    11    TMP_PATH=""
    12  fi
    13}
    14trap 'cleanup $LINENO' ERR EXIT
    15
    16cd $TMP_PATH
    17git clone --depth 1 https://github.com/golang/go
    18
    19rm -rfv ${OUT_DIR}/{asm,dwarf,obj,objabi,src,sys,bio,goobj}
    20
    21# Move obj.
    22cp -rv ${TMP_PATH}/go/src/cmd/internal/obj ${OUT_DIR}/obj
    23find ${OUT_DIR}/obj -type f -exec sed -i "s_\"cmd/internal/obj_\"${BASE_PKG_PATH}/obj_g" {} \;
    24find ${OUT_DIR}/obj -type f -exec sed -i "s_\"cmd/internal/dwarf_\"${BASE_PKG_PATH}/dwarf_g" {} \;
    25find ${OUT_DIR}/obj -type f -exec sed -i "s_\"cmd/internal/src_\"${BASE_PKG_PATH}/src_g" {} \;
    26find ${OUT_DIR}/obj -type f -exec sed -i "s_\"cmd/internal/sys_\"${BASE_PKG_PATH}/sys_g" {} \;
    27find ${OUT_DIR}/obj -type f -exec sed -i "s_\"cmd/internal/bio_\"${BASE_PKG_PATH}/bio_g" {} \;
    28find ${OUT_DIR}/obj -type f -exec sed -i "s_\"cmd/internal/goobj_\"${BASE_PKG_PATH}/goobj_g" {} \;
    29# Move objabi.
    30cp -rv ${TMP_PATH}/go/src/cmd/internal/objabi ${OUT_DIR}/objabi
    31find ${OUT_DIR}/objabi -type f -exec sed -i "s_\"cmd/internal/obj_\"${BASE_PKG_PATH}/obj_g" {} \;
    32find ${OUT_DIR}/objabi -type f -exec sed -i "s_\"cmd/internal/dwarf_\"${BASE_PKG_PATH}/dwarf_g" {} \;
    33find ${OUT_DIR}/objabi -type f -exec sed -i "s_\"cmd/internal/src_\"${BASE_PKG_PATH}/src_g" {} \;
    34find ${OUT_DIR}/objabi -type f -exec sed -i "s_\"cmd/internal/sys_\"${BASE_PKG_PATH}/sys_g" {} \;
    35find ${OUT_DIR}/objabi -type f -exec sed -i "s_\"cmd/internal/bio_\"${BASE_PKG_PATH}/bio_g" {} \;
    36find ${OUT_DIR}/objabi -type f -exec sed -i "s_\"cmd/internal/goobj_\"${BASE_PKG_PATH}/goobj_g" {} \;
    37# Move arch.
    38mkdir -pv ${OUT_DIR}/asm
    39cp -rv ${TMP_PATH}/go/src/cmd/asm/internal/arch ${OUT_DIR}/asm/arch
    40find ${OUT_DIR}/asm/arch -type f -exec sed -i "s_\"cmd/internal/obj_\"${BASE_PKG_PATH}/obj_g" {} \;
    41find ${OUT_DIR}/asm/arch -type f -exec sed -i "s_\"cmd/internal/dwarf_\"${BASE_PKG_PATH}/dwarf_g" {} \;
    42find ${OUT_DIR}/asm/arch -type f -exec sed -i "s_\"cmd/internal/src_\"${BASE_PKG_PATH}/src_g" {} \;
    43find ${OUT_DIR}/asm/arch -type f -exec sed -i "s_\"cmd/internal/sys_\"${BASE_PKG_PATH}/sys_g" {} \;
    44find ${OUT_DIR}/asm/arch -type f -exec sed -i "s_\"cmd/internal/bio_\"${BASE_PKG_PATH}/bio_g" {} \;
    45find ${OUT_DIR}/asm/arch -type f -exec sed -i "s_\"cmd/internal/goobj_\"${BASE_PKG_PATH}/goobj_g" {} \;
    46# Move goobj.
    47cp -rv ${TMP_PATH}/go/src/cmd/internal/goobj ${OUT_DIR}/goobj
    48find ${OUT_DIR}/goobj -type f -exec sed -i "s_\"cmd/internal/obj_\"${BASE_PKG_PATH}/obj_g" {} \;
    49find ${OUT_DIR}/goobj -type f -exec sed -i "s_\"cmd/internal/bio_\"${BASE_PKG_PATH}/bio_g" {} \;
    50find ${OUT_DIR}/goobj -type f -exec sed -i "s_\"internal/unsafeheader_\"${BASE_PKG_PATH}/unsafeheader_g" {} \;
    51
    52# Move bio.
    53cp -rv ${TMP_PATH}/go/src/cmd/internal/bio ${OUT_DIR}/bio
    54# Move unsafeheader.
    55cp -rv ${TMP_PATH}/go/src/internal/unsafeheader ${OUT_DIR}/unsafeheader
    56# Move dwarf.
    57cp -rv ${TMP_PATH}/go/src/cmd/internal/dwarf ${OUT_DIR}/dwarf
    58find ${OUT_DIR}/dwarf -type f -exec sed -i "s_\"cmd/internal/obj_\"${BASE_PKG_PATH}/obj_g" {} \;
    59# Move src.
    60cp -rv ${TMP_PATH}/go/src/cmd/internal/src ${OUT_DIR}/src
    61# Move sys.
    62cp -rv ${TMP_PATH}/go/src/cmd/internal/sys ${OUT_DIR}/sys
    63
    64
    65# Rewrite identifiers for generated (at build time) constants.
    66find ${OUT_DIR}/objabi -type f -exec sed -i "s/stackGuardMultiplierDefault/1/g" {} \;
    67find ${OUT_DIR}/objabi -type f -exec sed -i "s/defaultGOOS/\"linux\"/g" {} \;
    68find ${OUT_DIR}/objabi -type f -exec sed -i "s/defaultGOARCH/\"$(go env GOARCH)\"/g" {} \;
    69
    70find ${OUT_DIR}/objabi -type f -exec sed -i "s/defaultGO386/\"\"/g" {} \;
    71find ${OUT_DIR}/objabi -type f -exec sed -i "s/defaultGOARM/\"7\"/g" {} \;
    72find ${OUT_DIR}/objabi -type f -exec sed -i "s/defaultGOMIPS64/\"hardfloat\"/g" {} \;
    73find ${OUT_DIR}/objabi -type f -exec sed -i "s/defaultGOMIPS/\"hardfloat\"/g" {} \;
    74find ${OUT_DIR}/objabi -type f -exec sed -i "s/defaultGOPPC64/\"power8\"/g" {} \;
    75find ${OUT_DIR}/objabi -type f -exec sed -i "s/defaultGO_LDSO/\"\"/g" {} \;
    76find ${OUT_DIR}/objabi -type f -exec sed -i "s/= version/= \"\"/g" {} \;
    77find ${OUT_DIR}/objabi -type f -exec sed -i "s/defaultGO_EXTLINK_ENABLED/\"\"/g" {} \;
    78find ${OUT_DIR}/objabi -type f -exec sed -i "s/goexperiment/\"\"/g" {} \;
    79
    80
    81# Remove tests (they have package dependencies we could do without).
    82find ${OUT_DIR} -name "*_test.go" -type f -delete
    83
    84# Write README.
    85cat > ${OUT_DIR}/README.md << "EOF"
    86# golang-asm
    87
    88A mirror of the assembler from the Go compiler, with import paths re-written for the assembler to be functional as a standalone library.
    89
    90License as per the Go project.
    91
    92# Status
    93
    94Works, but expect to dig into the assembler godoc's to work out what to set different parameters of `obj.Prog` to get it to generate specific instructions.
    95
    96# Example
    97
    98Demonstrates assembly of a NOP & an ADD instruction on x86-64.
    99
   100```go
   101
   102package main
   103
   104import (
   105	"fmt"
   106
   107	asm "github.com/twitchyliquid64/golang-asm"
   108	"github.com/twitchyliquid64/golang-asm/obj"
   109	"github.com/twitchyliquid64/golang-asm/obj/x86"
   110)
   111
   112func noop(builder *asm.Builder) *obj.Prog {
   113	prog := builder.NewProg()
   114	prog.As = x86.ANOPL
   115	prog.From.Type = obj.TYPE_REG
   116	prog.From.Reg = x86.REG_AX
   117	return prog
   118}
   119
   120func addImmediateByte(builder *asm.Builder, in int32) *obj.Prog {
   121	prog := builder.NewProg()
   122	prog.As = x86.AADDB
   123	prog.To.Type = obj.TYPE_REG
   124	prog.To.Reg = x86.REG_AL
   125	prog.From.Type = obj.TYPE_CONST
   126	prog.From.Offset = int64(in)
   127	return prog
   128}
   129
   130func movImmediateByte(builder *asm.Builder, reg int16, in int32) *obj.Prog {
   131	prog := builder.NewProg()
   132	prog.As = x86.AMOVB
   133	prog.To.Type = obj.TYPE_REG
   134	prog.To.Reg = reg
   135	prog.From.Type = obj.TYPE_CONST
   136	prog.From.Offset = int64(in)
   137	return prog
   138}
   139
   140func main() {
   141	b, _ := asm.NewBuilder("amd64", 64)
   142	b.AddInstruction(noop(b))
   143	b.AddInstruction(movImmediateByte(b, x86.REG_AL, 16))
   144	b.AddInstruction(addImmediateByte(b, 16))
   145	fmt.Printf("Bin: %x\n", b.Assemble())
   146}
   147
   148```
   149
   150# Working out the parameters of `obj.Prog`
   151
   152This took me some time to work out, so I'll write a bit here.
   153
   154## Use these references
   155
   156 * `obj.Prog` - [godoc](https://godoc.org/github.com/golang/go/src/cmd/internal/obj#Prog)
   157  * Some instructions (like NOP, JMP) are abstract per-platform & can be found [here](https://godoc.org/github.com/golang/go/src/cmd/internal/obj#As)
   158
   159 * (for amd64) `x86 pkg-constants` - [registers & instructions](https://godoc.org/github.com/golang/go/src/cmd/internal/obj/x86#pkg-constant)
   160
   161## Instruction constants have a naming scheme
   162
   163Instructions are defined as constants in the package for the relavant architecture, and have an 'A' prefix and a size suffix.
   164
   165For example, the MOV instruction for 64 bits of data is `AMOVQ` (well, at least in amd64).
   166
   167## Search the go source for usage of a given instruction
   168
   169For example, if I wanted to work out how to emit the MOV instruction for 64bits, I would search the go source on github for `AMOVQ` or `x86.AMOVQ`. Normally, you see find a few examples where the compiler backend fills in a `obj.Prog` structure, and you follow it's lead.
   170EOF
   171
   172# Write license file.
   173cat > ${OUT_DIR}/LICENSE << "EOF"
   174Copyright (c) 2009 The Go Authors. All rights reserved.
   175
   176Redistribution and use in source and binary forms, with or without
   177modification, are permitted provided that the following conditions are
   178met:
   179
   180   * Redistributions of source code must retain the above copyright
   181notice, this list of conditions and the following disclaimer.
   182   * Redistributions in binary form must reproduce the above
   183copyright notice, this list of conditions and the following disclaimer
   184in the documentation and/or other materials provided with the
   185distribution.
   186   * Neither the name of Google Inc. nor the names of its
   187contributors may be used to endorse or promote products derived from
   188this software without specific prior written permission.
   189
   190THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   191"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   192LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
   193A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
   194OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   195SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOTto be standalone
   196LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   197DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   198THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   199(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
   200OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   201EOF

View as plain text