Skip to content
Permalink
Browse files

all: use internal objcopy implementation

This lessens the dependency on binutils (e.g. arm-none-eabi-objcopy).
  • Loading branch information...
aykevl authored and deadprogram committed Feb 23, 2019
1 parent 3538ba9 commit 4f932b6e669eece19b2adcbb690650a668a67fad
Showing with 90 additions and 19 deletions.
  1. +9 −0 Gopkg.lock
  2. +3 −10 main.go
  3. +78 −0 objcopy.go
  4. +0 −7 target.go
  5. +0 −1 targets/avr.json
  6. +0 −1 targets/cortex-m.json

Some generated files are not rendered by default. Learn more.

Oops, something went wrong.
13 main.go
@@ -259,19 +259,12 @@ func Compile(pkgName, outpath string, spec *TargetSpec, config *BuildConfig, act
}
}

// Get an Intel .hex file or .bin file from the .elf file.
if outext == ".hex" || outext == ".bin" {
// Get an Intel .hex file or .bin file from the .elf file.
tmppath = filepath.Join(dir, "main"+outext)
format := map[string]string{
".hex": "ihex",
".bin": "binary",
}[outext]
cmd := exec.Command(spec.Objcopy, "-O", format, executable, tmppath)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err = cmd.Run()
err := Objcopy(executable, tmppath)
if err != nil {
return &commandError{"failed to extract " + format + " from", executable, err}
return err
}
}
return action(tmppath)
@@ -0,0 +1,78 @@
package main

import (
"debug/elf"
"os"
"path/filepath"

"github.com/marcinbor85/gohex"
)

// ObjcopyError is an error returned by functions that act like objcopy.
type ObjcopyError struct {
Op string
Err error
}

func (e ObjcopyError) Error() string {
if e.Err == nil {
return e.Op
}
return e.Op + ": " + e.Err.Error()
}

// ExtractTextSegment returns the .text segment and the first address from the
// ELF file in the given path.
func ExtractTextSegment(path string) (uint64, []byte, error) {
f, err := elf.Open(path)
if err != nil {
return 0, nil, ObjcopyError{"failed to open ELF file to extract text segment", err}
}
defer f.Close()

text := f.Section(".text")
if text == nil {
return 0, nil, ObjcopyError{"file does not contain .text segment: " + path, nil}
}
data, err := text.Data()
if err != nil {
return 0, nil, ObjcopyError{"failed to extract .text segment from ELF file", err}
}
return text.Addr, data, nil
}

// Objcopy converts an ELF file to a different (simpler) output file format:
// .bin or .hex. It extracts only the .text section.
func Objcopy(infile, outfile string) error {
f, err := os.OpenFile(outfile, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666)
if err != nil {
return err
}
defer f.Close()

// Read the .text segment.
addr, data, err := ExtractTextSegment(infile)
if err != nil {
return err
}

// Write to the file, in the correct format.
switch filepath.Ext(outfile) {
case ".bin":
// The address is not stored in a .bin file (therefore you
// should use .hex files in most cases).
_, err := f.Write(data)
return err
case ".hex":
mem := gohex.NewMemory()
mem.SetStartAddress(uint32(addr)) // ignored in most cases (Intel-specific)
err := mem.AddBinary(uint32(addr), data)
if err != nil {
return ObjcopyError{"failed to create .hex file", err}
}
mem.DumpIntelHex(f, 32) // TODO: handle error
return nil
default:
panic("unreachable")
}
}
@@ -31,7 +31,6 @@ type TargetSpec struct {
CFlags []string `json:"cflags"`
LDFlags []string `json:"ldflags"`
ExtraFiles []string `json:"extra-files"`
Objcopy string `json:"objcopy"`
Emulator []string `json:"emulator"`
Flasher string `json:"flash"`
OCDDaemon []string `json:"ocd-daemon"`
@@ -72,9 +71,6 @@ func (spec *TargetSpec) copyProperties(spec2 *TargetSpec) {
spec.CFlags = append(spec.CFlags, spec2.CFlags...)
spec.LDFlags = append(spec.LDFlags, spec2.LDFlags...)
spec.ExtraFiles = append(spec.ExtraFiles, spec2.ExtraFiles...)
if spec2.Objcopy != "" {
spec.Objcopy = spec2.Objcopy
}
if len(spec2.Emulator) != 0 {
spec.Emulator = spec2.Emulator
}
@@ -217,7 +213,6 @@ func defaultTarget(goos, goarch, triple string) (*TargetSpec, error) {
BuildTags: []string{goos, goarch},
Compiler: commands["clang"],
Linker: "cc",
Objcopy: "objcopy",
GDB: "gdb",
GDBCmds: []string{"run"},
}
@@ -230,13 +225,11 @@ func defaultTarget(goos, goarch, triple string) (*TargetSpec, error) {
// Some educated guesses as to how to invoke helper programs.
if goarch == "arm" && goos == "linux" {
spec.Linker = "arm-linux-gnueabihf-gcc"
spec.Objcopy = "arm-linux-gnueabihf-objcopy"
spec.GDB = "arm-linux-gnueabihf-gdb"
spec.Emulator = []string{"qemu-arm", "-L", "/usr/arm-linux-gnueabihf"}
}
if goarch == "arm64" && goos == "linux" {
spec.Linker = "aarch64-linux-gnu-gcc"
spec.Objcopy = "aarch64-linux-gnu-objcopy"
spec.GDB = "aarch64-linux-gnu-gdb"
spec.Emulator = []string{"qemu-aarch64", "-L", "/usr/aarch64-linux-gnu"}
}
@@ -4,7 +4,6 @@
"goarch": "wasm",
"compiler": "avr-gcc",
"linker": "avr-gcc",
"objcopy": "avr-objcopy",
"ldflags": [
"-T", "targets/avr.ld",
"-Wl,--gc-sections"
@@ -16,6 +16,5 @@
"ldflags": [
"--gc-sections"
],
"objcopy": "arm-none-eabi-objcopy",
"gdb": "arm-none-eabi-gdb"
}

0 comments on commit 4f932b6

Please sign in to comment.
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.