Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 15 additions & 4 deletions compiler/symbol.go
Original file line number Diff line number Diff line change
Expand Up @@ -630,7 +630,7 @@ func (c *compilerContext) addStandardAttributes(llvmFn llvm.Value) {
// linkName is equal to .RelString(nil) on a global and extern is false, but for
// some symbols this is different (due to //go:extern for example).
type globalInfo struct {
linkName string // go:extern
linkName string // go:extern, go:linkname
extern bool // go:extern
align int // go:align
section string // go:section
Expand Down Expand Up @@ -715,14 +715,14 @@ func (c *compilerContext) getGlobalInfo(g *ssa.Global) globalInfo {
// Check for //go: pragmas, which may change the link name (among others).
doc := c.astComments[info.linkName]
if doc != nil {
info.parsePragmas(doc)
info.parsePragmas(doc, c, g)
}
return info
}

// Parse //go: pragma comments from the source. In particular, it parses the
// //go:extern pragma on globals.
func (info *globalInfo) parsePragmas(doc *ast.CommentGroup) {
// //go:extern and //go:linkname pragmas on globals.
func (info *globalInfo) parsePragmas(doc *ast.CommentGroup, c *compilerContext, g *ssa.Global) {
for _, comment := range doc.List {
if !strings.HasPrefix(comment.Text, "//go:") {
continue
Expand All @@ -743,6 +743,17 @@ func (info *globalInfo) parsePragmas(doc *ast.CommentGroup) {
if len(parts) == 2 {
info.section = parts[1]
}
case "//go:linkname":
if len(parts) != 3 || parts[1] != g.Name() {
continue
}
// Only enable go:linkname when the package imports "unsafe".
// This is a slightly looser requirement than what gc uses: gc
// requires the file to import "unsafe", not the package as a
// whole.
if hasUnsafeImport(g.Pkg.Pkg) {
info.linkName = parts[2]
}
}
}
}
Expand Down
6 changes: 3 additions & 3 deletions monitor.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ func Monitor(executable, port string, config *compileopts.Config) error {
// Use the RTT interface, which is documented (in part) here:
// https://wiki.segger.com/RTT

// Try to find the "machine.rttSerialInstance" symbol, which is the RTT
// control block.
// Try to find the "_SEGGER_RTT" symbol (machine.rttSerialInstance)
// symbol, which is the RTT control block.
file, err := elf.Open(executable)
if err != nil {
return fmt.Errorf("could not open ELF file to determine RTT control block: %w", err)
Expand All @@ -48,7 +48,7 @@ func Monitor(executable, port string, config *compileopts.Config) error {
}
var address uint64
for _, symbol := range symbols {
if symbol.Name == "machine.rttSerialInstance" {
if symbol.Name == "_SEGGER_RTT" {
address = symbol.Value
break
}
Expand Down
2 changes: 2 additions & 0 deletions src/machine/serial-rtt.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import (
)

// This symbol name is known by the compiler, see monitor.go.
//
//go:linkname rttSerialInstance _SEGGER_RTT
var rttSerialInstance rttSerial

var Serial = &rttSerialInstance
Expand Down