diff --git a/builder/ar.go b/builder/ar.go index 98d574fc4b..d70eaf9e09 100644 --- a/builder/ar.go +++ b/builder/ar.go @@ -5,6 +5,7 @@ import ( "debug/elf" "encoding/binary" "errors" + "fmt" "io" "os" "path/filepath" @@ -49,7 +50,7 @@ func makeArchive(archivePath string, objs []string) error { // Read the symbols and add them to the symbol table. dbg, err := elf.NewFile(objfile) if err != nil { - return err + return fmt.Errorf("failed to open file %s: %w", objpath, err) } symbols, err := dbg.Symbols() if err != nil { @@ -61,9 +62,8 @@ func makeArchive(archivePath string, objs []string) error { // Don't include local symbols (STB_LOCAL). continue } - if elf.ST_TYPE(symbol.Info) != elf.STT_FUNC { + if elf.ST_TYPE(symbol.Info) != elf.STT_FUNC && elf.ST_TYPE(symbol.Info) != elf.STT_OBJECT { // Not a function. - // TODO: perhaps globals variables should also be included? continue } // Include in archive. diff --git a/builder/picolibc.go b/builder/picolibc.go index 436c34815a..e73528b4c1 100644 --- a/builder/picolibc.go +++ b/builder/picolibc.go @@ -12,7 +12,17 @@ var Picolibc = Library{ name: "picolibc", cflags: func() []string { picolibcDir := filepath.Join(goenv.Get("TINYGOROOT"), "lib/picolibc/newlib/libc") - return []string{"-Werror", "-Wall", "-std=gnu11", "-D_COMPILING_NEWLIB", "-nostdlibinc", "-Xclang", "-internal-isystem", "-Xclang", picolibcDir + "/include", "-I" + picolibcDir + "/tinystdio", "-I" + goenv.Get("TINYGOROOT") + "/lib/picolibc-include"} + return []string{ + "-Werror", + "-Wall", + "-std=gnu11", + "-D_COMPILING_NEWLIB", + "-DTINY_STDIO", + "-nostdlibinc", + "-Xclang", "-internal-isystem", "-Xclang", picolibcDir + "/include", + "-I" + picolibcDir + "/tinystdio", + "-I" + goenv.Get("TINYGOROOT") + "/lib/picolibc-include", + } }, sourceDir: "lib/picolibc/newlib/libc", sources: func(target string) []string { @@ -21,6 +31,105 @@ var Picolibc = Library{ } var picolibcSources = []string{ + "../../../picolibc-stdio.c", + + "tinystdio/asprintf.c", + "tinystdio/atod_engine.c", + "tinystdio/atod_ryu.c", + "tinystdio/atof_engine.c", + "tinystdio/atof_ryu.c", + //"tinystdio/atold_engine.c", // have_long_double and not long_double_equals_double + "tinystdio/clearerr.c", + "tinystdio/compare_exchange.c", + "tinystdio/dtoa_data.c", + "tinystdio/dtoa_engine.c", + "tinystdio/dtoa_ryu.c", + "tinystdio/ecvtbuf.c", + "tinystdio/ecvt.c", + "tinystdio/ecvt_data.c", + "tinystdio/ecvtfbuf.c", + "tinystdio/ecvtf.c", + "tinystdio/ecvtf_data.c", + "tinystdio/exchange.c", + //"tinystdio/fclose.c", // posix-io + "tinystdio/fcvtbuf.c", + "tinystdio/fcvt.c", + "tinystdio/fcvtfbuf.c", + "tinystdio/fcvtf.c", + "tinystdio/fdevopen.c", + //"tinystdio/fdopen.c", // posix-io + "tinystdio/feof.c", + "tinystdio/ferror.c", + "tinystdio/fflush.c", + "tinystdio/fgetc.c", + "tinystdio/fgets.c", + "tinystdio/fileno.c", + "tinystdio/filestrget.c", + "tinystdio/filestrputalloc.c", + "tinystdio/filestrput.c", + //"tinystdio/fopen.c", // posix-io + "tinystdio/fprintf.c", + "tinystdio/fputc.c", + "tinystdio/fputs.c", + "tinystdio/fread.c", + "tinystdio/fscanf.c", + "tinystdio/fseek.c", + "tinystdio/ftell.c", + "tinystdio/ftoa_data.c", + "tinystdio/ftoa_engine.c", + "tinystdio/ftoa_ryu.c", + "tinystdio/fwrite.c", + "tinystdio/gcvtbuf.c", + "tinystdio/gcvt.c", + "tinystdio/gcvtfbuf.c", + "tinystdio/gcvtf.c", + "tinystdio/getchar.c", + "tinystdio/gets.c", + "tinystdio/matchcaseprefix.c", + "tinystdio/perror.c", + //"tinystdio/posixiob.c", // posix-io + //"tinystdio/posixio.c", // posix-io + "tinystdio/printf.c", + "tinystdio/putchar.c", + "tinystdio/puts.c", + "tinystdio/ryu_divpow2.c", + "tinystdio/ryu_log10.c", + "tinystdio/ryu_log2pow5.c", + "tinystdio/ryu_pow5bits.c", + "tinystdio/ryu_table.c", + "tinystdio/ryu_umul128.c", + "tinystdio/scanf.c", + "tinystdio/setbuf.c", + "tinystdio/setvbuf.c", + //"tinystdio/sflags.c", // posix-io + "tinystdio/snprintf.c", + "tinystdio/snprintfd.c", + "tinystdio/snprintff.c", + "tinystdio/sprintf.c", + "tinystdio/sprintfd.c", + "tinystdio/sprintff.c", + "tinystdio/sscanf.c", + "tinystdio/strfromd.c", + "tinystdio/strfromf.c", + "tinystdio/strtod.c", + "tinystdio/strtod_l.c", + "tinystdio/strtof.c", + //"tinystdio/strtold.c", // have_long_double and not long_double_equals_double + //"tinystdio/strtold_l.c", // have_long_double and not long_double_equals_double + "tinystdio/ungetc.c", + "tinystdio/vasprintf.c", + "tinystdio/vfiprintf.c", + "tinystdio/vfiscanf.c", + "tinystdio/vfprintf.c", + "tinystdio/vfprintff.c", + "tinystdio/vfscanf.c", + "tinystdio/vfscanff.c", + "tinystdio/vprintf.c", + "tinystdio/vscanf.c", + "tinystdio/vsnprintf.c", + "tinystdio/vsprintf.c", + "tinystdio/vsscanf.c", + "string/bcmp.c", "string/bcopy.c", "string/bzero.c", diff --git a/lib/picolibc b/lib/picolibc index 80528c684b..3bf0a10736 160000 --- a/lib/picolibc +++ b/lib/picolibc @@ -1 +1 @@ -Subproject commit 80528c684b10aaee977397e7eb40c4784e6dc433 +Subproject commit 3bf0a107362bd2b2048733e92f33b6cfeb6899e8 diff --git a/lib/picolibc-stdio.c b/lib/picolibc-stdio.c new file mode 100644 index 0000000000..23013bd818 --- /dev/null +++ b/lib/picolibc-stdio.c @@ -0,0 +1,12 @@ +#include + +// Defined in the runtime package. Writes to the default console (usually, the +// first UART or an USB-CDC device). +int runtime_putchar(char, FILE*); + +// Define stdin, stdout, and stderr as a single object. +// This object must not reside in ROM. +static FILE __stdio = FDEV_SETUP_STREAM(runtime_putchar, NULL, NULL, _FDEV_SETUP_WRITE); + +// Define the underlying structs for stdin, stdout, and stderr. +FILE *const __iob[3] = { &__stdio, &__stdio, &__stdio }; diff --git a/src/runtime/baremetal.go b/src/runtime/baremetal.go index 4e81a9cc92..457aa61700 100644 --- a/src/runtime/baremetal.go +++ b/src/runtime/baremetal.go @@ -51,6 +51,11 @@ func libc_abort() { abort() } +//export runtime_putchar +func runtime_putchar(c byte) { + putchar(c) +} + //go:linkname syscall_Exit syscall.Exit func syscall_Exit(code int) { abort() diff --git a/testdata/cgo/main.go b/testdata/cgo/main.go index 2e286baaa3..68d5bda1ed 100644 --- a/testdata/cgo/main.go +++ b/testdata/cgo/main.go @@ -139,6 +139,8 @@ func main() { // libc: test basic stdio functionality println("SEEK_CUR:", C.SEEK_CUR) + putsBuf := []byte("line written using C puts\x00") + C.puts((*C.char)(unsafe.Pointer(&putsBuf[0]))) } func printUnion(union C.joined_t) C.joined_t { diff --git a/testdata/cgo/out.txt b/testdata/cgo/out.txt index 6b2cc5e5b5..943ca2d03f 100644 --- a/testdata/cgo/out.txt +++ b/testdata/cgo/out.txt @@ -62,3 +62,4 @@ enum width matches: true CFLAGS value: 17 copied string: foobar SEEK_CUR: 1 +line written using C puts