feat: add libc
This commit is contained in:
@@ -8,8 +8,11 @@ import (
|
|||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/internal/clang"
|
||||||
|
|
||||||
"github.com/goplus/llgo/internal/env"
|
"github.com/goplus/llgo/internal/env"
|
||||||
"github.com/goplus/llgo/internal/targets"
|
"github.com/goplus/llgo/internal/targets"
|
||||||
"github.com/goplus/llgo/internal/xtool/llvm"
|
"github.com/goplus/llgo/internal/xtool/llvm"
|
||||||
@@ -215,6 +218,70 @@ func getESPClangPlatform(goos, goarch string) string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getOrCompileLibc(cc, linkerName, libcName string, ccflags, exportLdFlags []string) (ldflags []string, err error) {
|
||||||
|
baseDir := filepath.Join(cacheRoot(), "crosscompile")
|
||||||
|
libcDir := filepath.Join(baseDir, libcName)
|
||||||
|
libcArchive := filepath.Join(libcDir, "libc.a")
|
||||||
|
// fast-path: compiled already
|
||||||
|
if _, err = os.Stat(libcArchive); !os.IsNotExist(err) {
|
||||||
|
ldflags = append(ldflags, "-nostdlib", "-L", libcDir, "-lc")
|
||||||
|
return ldflags, nil
|
||||||
|
}
|
||||||
|
compileConfig, err := getCompileLibcConfigByName(baseDir, libcName)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
tempDir, err := os.MkdirTemp("", "compile*")
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer os.RemoveAll(tempDir)
|
||||||
|
|
||||||
|
fmt.Fprintf(os.Stderr, "%s not found in LLGO_ROOT or cache, will download and compile.\n", libcDir)
|
||||||
|
if err = checkDownloadAndExtractLibc(compileConfig.Url, libcDir, compileConfig.ArchiveSrcDir); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
compileLDFlags := append(slices.Clone(exportLdFlags), compileConfig.LDFlags...)
|
||||||
|
|
||||||
|
cfg := clang.NewConfig(cc, ccflags, compileConfig.CFlags, compileLDFlags, linkerName)
|
||||||
|
|
||||||
|
var objFiles []string
|
||||||
|
|
||||||
|
compiler := clang.NewCompiler(cfg)
|
||||||
|
linker := clang.NewLinker(cfg)
|
||||||
|
|
||||||
|
compiler.Verbose = true
|
||||||
|
linker.Verbose = true
|
||||||
|
fmt.Fprintf(os.Stderr, "Start to compile libc %s to %s...\n", libcName, libcArchive)
|
||||||
|
|
||||||
|
for _, file := range compileConfig.Files {
|
||||||
|
var tempObjFile *os.File
|
||||||
|
tempObjFile, err = os.CreateTemp(tempDir, "libc*.o")
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Fprintf(os.Stderr, "Compile libc file %s to %s...\n", file, tempObjFile.Name())
|
||||||
|
|
||||||
|
err = compiler.Compile("-o", tempObjFile.Name(), "-x", "c", "-c", file)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
objFiles = append(objFiles, tempObjFile.Name())
|
||||||
|
}
|
||||||
|
|
||||||
|
args := []string{"-o", libcArchive}
|
||||||
|
args = append(args, objFiles...)
|
||||||
|
|
||||||
|
err = linker.Link(args...)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ldflags = append(ldflags, "-nostdlib", "-L", libcDir, "-lc")
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func use(goos, goarch string, wasiThreads bool) (export Export, err error) {
|
func use(goos, goarch string, wasiThreads bool) (export Export, err error) {
|
||||||
targetTriple := llvm.GetTargetTriple(goos, goarch)
|
targetTriple := llvm.GetTargetTriple(goos, goarch)
|
||||||
llgoRoot := env.LLGoROOT()
|
llgoRoot := env.LLGoROOT()
|
||||||
@@ -574,6 +641,15 @@ func useTarget(targetName string) (export Export, err error) {
|
|||||||
}
|
}
|
||||||
ldflags = append(ldflags, "-L", env.LLGoROOT()) // search targets/*.ld
|
ldflags = append(ldflags, "-L", env.LLGoROOT()) // search targets/*.ld
|
||||||
|
|
||||||
|
if config.Libc != "" {
|
||||||
|
var libcLDFlags []string
|
||||||
|
libcLDFlags, err = getOrCompileLibc(export.CC, export.Linker, config.Libc, ccflags, ldflags)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ldflags = append(ldflags, libcLDFlags...)
|
||||||
|
}
|
||||||
|
|
||||||
// Combine with config flags and expand template variables
|
// Combine with config flags and expand template variables
|
||||||
export.CFLAGS = cflags
|
export.CFLAGS = cflags
|
||||||
export.CCFLAGS = ccflags
|
export.CCFLAGS = ccflags
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
@@ -78,6 +79,47 @@ func checkDownloadAndExtractESPClang(platformSuffix, dir string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func checkDownloadAndExtractLibc(url, dstDir, internalArchiveSrcDir string) error {
|
||||||
|
// Check if already exists
|
||||||
|
if _, err := os.Stat(dstDir); err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create lock file path for the final destination
|
||||||
|
lockPath := dstDir + ".lock"
|
||||||
|
lockFile, err := acquireLock(lockPath)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to acquire lock: %w", err)
|
||||||
|
}
|
||||||
|
defer releaseLock(lockFile)
|
||||||
|
|
||||||
|
// Double-check after acquiring lock
|
||||||
|
if _, err := os.Stat(dstDir); err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
description := fmt.Sprintf("Libc %s", path.Base(url))
|
||||||
|
|
||||||
|
// Use temporary extraction directory
|
||||||
|
tempExtractDir := dstDir + ".extract"
|
||||||
|
if err := downloadAndExtractArchive(url, tempExtractDir, description); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer os.RemoveAll(tempExtractDir)
|
||||||
|
|
||||||
|
srcDir := tempExtractDir
|
||||||
|
|
||||||
|
if internalArchiveSrcDir != "" {
|
||||||
|
srcDir = filepath.Join(tempExtractDir, internalArchiveSrcDir)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := os.Rename(srcDir, dstDir); err != nil {
|
||||||
|
return fmt.Errorf("failed to rename libc directory: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// acquireLock creates and locks a file to prevent concurrent operations
|
// acquireLock creates and locks a file to prevent concurrent operations
|
||||||
func acquireLock(lockPath string) (*os.File, error) {
|
func acquireLock(lockPath string) (*os.File, error) {
|
||||||
// Ensure the parent directory exists
|
// Ensure the parent directory exists
|
||||||
|
|||||||
185
internal/crosscompile/libc.go
Normal file
185
internal/crosscompile/libc.go
Normal file
@@ -0,0 +1,185 @@
|
|||||||
|
package crosscompile
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CompileLibcConfig represents libc compilation configuration
|
||||||
|
type compileLibcConfig struct {
|
||||||
|
Url string
|
||||||
|
Name string // Libc name (e.g., "picolibc", "musl", "glibc")
|
||||||
|
Files []string // List of source files to compile
|
||||||
|
CFlags []string // C compiler flags specific to this libc
|
||||||
|
LDFlags []string // Linker flags
|
||||||
|
ArchiveSrcDir string
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetCompileLibcConfigByName retrieves libc compilation configuration by name
|
||||||
|
// Returns compilation file lists and corresponding cflags
|
||||||
|
func getCompileLibcConfigByName(baseDir, libcName string) (*compileLibcConfig, error) {
|
||||||
|
if libcName == "" {
|
||||||
|
return nil, fmt.Errorf("libc name cannot be empty")
|
||||||
|
}
|
||||||
|
libcDir := filepath.Join(baseDir, libcName)
|
||||||
|
|
||||||
|
switch libcName {
|
||||||
|
case "picolibc":
|
||||||
|
return getPicolibcConfig(libcDir), nil
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("unsupported libc: %s", libcName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// getPicolibcConfig returns configuration for picolibc
|
||||||
|
func getPicolibcConfig(baseDir string) *compileLibcConfig {
|
||||||
|
libcIncludeDir := filepath.Join(baseDir, "libc", "include")
|
||||||
|
libmIncludeDir := filepath.Join(baseDir, "libm", "common")
|
||||||
|
localeIncludeDir := filepath.Join(baseDir, "libc", "locale")
|
||||||
|
|
||||||
|
os.MkdirAll(baseDir, 0700)
|
||||||
|
|
||||||
|
headerFile, _ := os.Create(filepath.Join(baseDir, "picolibc.h"))
|
||||||
|
headerFile.Close()
|
||||||
|
|
||||||
|
return &compileLibcConfig{
|
||||||
|
Url: "https://github.com/picolibc/picolibc/releases/download/1.8.10/picolibc-1.8.10.tar.xz",
|
||||||
|
Name: "picolibc",
|
||||||
|
Files: []string{
|
||||||
|
filepath.Join(baseDir, "libc", "string", "bcmp.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "bcopy.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "bzero.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "explicit_bzero.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "ffsl.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "ffsll.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "fls.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "flsl.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "flsll.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "gnu_basename.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "index.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "memccpy.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "memchr.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "memcmp.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "memcpy.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "memmem.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "memmove.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "mempcpy.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "memrchr.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "memset.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "rawmemchr.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "rindex.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "stpcpy.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "stpncpy.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "strcasecmp.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "strcasecmp_l.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "strcasestr.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "strcat.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "strchr.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "strchrnul.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "strcmp.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "strcoll.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "strcoll_l.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "strcpy.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "strcspn.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "strerror_r.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "strlcat.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "strlcpy.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "strlen.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "strlwr.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "strncasecmp.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "strncasecmp_l.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "strncat.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "strncmp.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "strncpy.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "strndup.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "strnlen.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "strnstr.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "strpbrk.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "strrchr.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "strsep.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "strsignal.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "strspn.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "strstr.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "strtok.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "strtok_r.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "strupr.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "strverscmp.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "strxfrm.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "strxfrm_l.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "swab.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "timingsafe_bcmp.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "timingsafe_memcmp.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "strerror.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "wcpcpy.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "wcpncpy.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "wcscasecmp.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "wcscasecmp_l.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "wcscat.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "wcschr.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "wcscmp.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "wcscoll.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "wcscoll_l.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "wcscpy.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "wcscspn.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "wcsdup.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "wcslcat.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "wcslcpy.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "wcslen.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "wcsncasecmp.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "wcsncasecmp_l.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "wcsncat.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "wcsncmp.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "wcsncpy.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "wcsnlen.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "wcspbrk.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "wcsrchr.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "wcsspn.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "wcsstr.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "wcstok.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "wcswidth.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "wcsxfrm.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "wcsxfrm_l.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "wcwidth.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "wmemchr.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "wmemcmp.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "wmemcpy.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "wmemmove.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "wmempcpy.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "wmemset.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "string", "xpg_strerror_r.c"),
|
||||||
|
|
||||||
|
filepath.Join(baseDir, "libc", "stdlib", "nano-calloc.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "stdlib", "nano-malloc.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "stdlib", "nano-pvalloc.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "stdlib", "nano-realloc.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "stdlib", "nano-valloc.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "stdlib", "rand.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "stdlib", "srand.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "stdlib", "nano-free.c"),
|
||||||
|
|
||||||
|
filepath.Join(baseDir, "libc", "tinystdio", "printf.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "tinystdio", "putchar.c"),
|
||||||
|
filepath.Join(baseDir, "libc", "tinystdio", "puts.c"),
|
||||||
|
},
|
||||||
|
CFlags: []string{
|
||||||
|
"-D_COMPILING_NEWLIB",
|
||||||
|
"-D_HAVE_ALIAS_ATTRIBUTE",
|
||||||
|
"-DTINY_STDIO",
|
||||||
|
"-DPOSIX_IO",
|
||||||
|
"-DFORMAT_DEFAULT_INTEGER",
|
||||||
|
"-D_IEEE_LIBM",
|
||||||
|
"-D__OBSOLETE_MATH_FLOAT=1",
|
||||||
|
"-D__OBSOLETE_MATH_DOUBLE=0",
|
||||||
|
"-D_WANT_IO_C99_FORMATS",
|
||||||
|
"-nostdlib",
|
||||||
|
"-isystem" + libcIncludeDir,
|
||||||
|
"-I" + libmIncludeDir,
|
||||||
|
"-I" + localeIncludeDir,
|
||||||
|
"-I" + baseDir,
|
||||||
|
"-I" + filepath.Join(baseDir, "libc", "tinystdio"),
|
||||||
|
},
|
||||||
|
LDFlags: []string{"-nostdlib"},
|
||||||
|
ArchiveSrcDir: filepath.Join("picolibc-1.8.10", "newlib"),
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,6 +16,7 @@ type Config struct {
|
|||||||
GOARCH string `json:"goarch"`
|
GOARCH string `json:"goarch"`
|
||||||
|
|
||||||
// Compiler and linker configuration
|
// Compiler and linker configuration
|
||||||
|
Libc string `json:"libc"`
|
||||||
Linker string `json:"linker"`
|
Linker string `json:"linker"`
|
||||||
LinkerScript string `json:"linkerscript"`
|
LinkerScript string `json:"linkerscript"`
|
||||||
CFlags []string `json:"cflags"`
|
CFlags []string `json:"cflags"`
|
||||||
|
|||||||
@@ -134,6 +134,9 @@ func (l *Loader) mergeConfig(dst, src *Config) {
|
|||||||
if src.GOARCH != "" {
|
if src.GOARCH != "" {
|
||||||
dst.GOARCH = src.GOARCH
|
dst.GOARCH = src.GOARCH
|
||||||
}
|
}
|
||||||
|
if src.Libc != "" {
|
||||||
|
dst.Libc = src.Libc
|
||||||
|
}
|
||||||
if src.Linker != "" {
|
if src.Linker != "" {
|
||||||
dst.Linker = src.Linker
|
dst.Linker = src.Linker
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -97,14 +97,6 @@ _heap_end = ORIGIN(DRAM) + LENGTH(DRAM);
|
|||||||
|
|
||||||
_stack_size = 4K;
|
_stack_size = 4K;
|
||||||
|
|
||||||
/* From ESP-IDF:
|
|
||||||
* components/esp_rom/esp32/ld/esp32.rom.newlib-funcs.ld
|
|
||||||
* This is the subset that is sometimes used by LLVM during codegen, and thus
|
|
||||||
* must always be present.
|
|
||||||
*/
|
|
||||||
memcpy = 0x4000c2c8;
|
|
||||||
memmove = 0x4000c3c0;
|
|
||||||
memset = 0x4000c44c;
|
|
||||||
|
|
||||||
/* From ESP-IDF:
|
/* From ESP-IDF:
|
||||||
* components/esp_rom/esp32/ld/esp32.rom.libgcc.ld
|
* components/esp_rom/esp32/ld/esp32.rom.libgcc.ld
|
||||||
@@ -200,3 +192,9 @@ __umodsi3 = 0x4000c7d0;
|
|||||||
__umulsidi3 = 0x4000c7d8;
|
__umulsidi3 = 0x4000c7d8;
|
||||||
__unorddf2 = 0x400637f4;
|
__unorddf2 = 0x400637f4;
|
||||||
__unordsf2 = 0x40063478;
|
__unordsf2 = 0x40063478;
|
||||||
|
|
||||||
|
INCLUDE "targets/esp32.rom.newlib-data.ld";
|
||||||
|
INCLUDE "targets/esp32.rom.newlib-funcs.ld";
|
||||||
|
INCLUDE "targets/esp32.rom.newlib-locale.ld";
|
||||||
|
INCLUDE "targets/esp32.rom.newlib-nano.ld";
|
||||||
|
INCLUDE "targets/esp32.rom.newlib-time.ld";
|
||||||
|
|||||||
23
targets/esp32.rom.newlib-data.ld
Normal file
23
targets/esp32.rom.newlib-data.ld
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
/* These are the .bss/.data symbols used by newlib functions present in ESP32 ROM.
|
||||||
|
See also esp32.rom.newlib-funcs.ld for the list of general newlib functions,
|
||||||
|
and esp32.rom.newlib-nano.ld for "nano" versions of printf/scanf family of functions.
|
||||||
|
|
||||||
|
Unlike other ROM functions and data which are exported using PROVIDE, which declares
|
||||||
|
weak symbols, newlib related functions are exported using assignment,
|
||||||
|
which declares strong symbols. This is done so that ROM functions are always
|
||||||
|
used instead of the ones provided by libc.a.
|
||||||
|
*/
|
||||||
|
|
||||||
|
_ctype_ = 0x3ff96354;
|
||||||
|
__ctype_ptr__ = 0x3ff96350;
|
||||||
|
environ = 0x3ffae0b4;
|
||||||
|
_global_impure_ptr = 0x3ffae0b0;
|
||||||
|
__mb_cur_max = 0x3ff96530;
|
||||||
|
__sf_fake_stderr = 0x3ff96458;
|
||||||
|
__sf_fake_stdin = 0x3ff96498;
|
||||||
|
__sf_fake_stdout = 0x3ff96478;
|
||||||
|
__wctomb = 0x3ff96540;
|
||||||
|
__sfp_lock = 0x3ffae0ac;
|
||||||
|
__sinit_lock = 0x3ffae0a8;
|
||||||
|
__env_lock_object = 0x3ffae0b8;
|
||||||
|
__tz_lock_object = 0x3ffae080;
|
||||||
130
targets/esp32.rom.newlib-funcs.ld
Normal file
130
targets/esp32.rom.newlib-funcs.ld
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
/* These are the newlib functions present in ESP32 ROM.
|
||||||
|
They should not be used when compiling with PSRAM cache workaround enabled.
|
||||||
|
See also esp32.rom.newlib-data.ld for the list of .data/.bss symbols
|
||||||
|
used by these functions, and esp32.rom.newlib-nano.ld for "nano" versions
|
||||||
|
of printf/scanf family of functions.
|
||||||
|
|
||||||
|
Unlike other ROM functions which are exported using PROVIDE, which declares
|
||||||
|
weak symbols, newlib related functions are exported using assignment,
|
||||||
|
which declares strong symbols. This is done so that ROM functions are always
|
||||||
|
used instead of the ones provided by libc.a.
|
||||||
|
|
||||||
|
Time functions were moved to the esp32.rom.newlib-time.ld file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
abs = 0x40056340;
|
||||||
|
__ascii_wctomb = 0x40058ef0;
|
||||||
|
atoi = 0x400566c4;
|
||||||
|
_atoi_r = 0x400566d4;
|
||||||
|
atol = 0x400566ec;
|
||||||
|
_atol_r = 0x400566fc;
|
||||||
|
bzero = 0x4000c1f4;
|
||||||
|
_cleanup = 0x40001df8;
|
||||||
|
_cleanup_r = 0x40001d48;
|
||||||
|
creat = 0x40000e8c;
|
||||||
|
div = 0x40056348;
|
||||||
|
__dummy_lock = 0x4000c728;
|
||||||
|
__dummy_lock_try = 0x4000c730;
|
||||||
|
__env_lock = 0x40001fd4;
|
||||||
|
__env_unlock = 0x40001fe0;
|
||||||
|
fclose = 0x400020ac;
|
||||||
|
_fclose_r = 0x40001fec;
|
||||||
|
fflush = 0x40059394;
|
||||||
|
_fflush_r = 0x40059320;
|
||||||
|
_findenv_r = 0x40001f44;
|
||||||
|
__fp_lock_all = 0x40001f1c;
|
||||||
|
__fp_unlock_all = 0x40001f30;
|
||||||
|
__fputwc = 0x40058da0;
|
||||||
|
fputwc = 0x40058ea8;
|
||||||
|
_fputwc_r = 0x40058e4c;
|
||||||
|
_fwalk = 0x4000c738;
|
||||||
|
_fwalk_reent = 0x4000c770;
|
||||||
|
_getenv_r = 0x40001fbc;
|
||||||
|
isalnum = 0x40000f04;
|
||||||
|
isalpha = 0x40000f18;
|
||||||
|
isascii = 0x4000c20c;
|
||||||
|
isblank = 0x40000f2c;
|
||||||
|
iscntrl = 0x40000f50;
|
||||||
|
isdigit = 0x40000f64;
|
||||||
|
isgraph = 0x40000f94;
|
||||||
|
islower = 0x40000f78;
|
||||||
|
isprint = 0x40000fa8;
|
||||||
|
ispunct = 0x40000fc0;
|
||||||
|
isspace = 0x40000fd4;
|
||||||
|
isupper = 0x40000fe8;
|
||||||
|
__itoa = 0x40056678;
|
||||||
|
itoa = 0x400566b4;
|
||||||
|
labs = 0x40056370;
|
||||||
|
ldiv = 0x40056378;
|
||||||
|
longjmp = 0x400562cc;
|
||||||
|
memccpy = 0x4000c220;
|
||||||
|
memchr = 0x4000c244;
|
||||||
|
memcmp = 0x4000c260;
|
||||||
|
memcpy = 0x4000c2c8;
|
||||||
|
memmove = 0x4000c3c0;
|
||||||
|
memrchr = 0x4000c400;
|
||||||
|
memset = 0x4000c44c;
|
||||||
|
qsort = 0x40056424;
|
||||||
|
rand = 0x40001058;
|
||||||
|
rand_r = 0x400010d4;
|
||||||
|
__sccl = 0x4000c498;
|
||||||
|
__sclose = 0x400011b8;
|
||||||
|
__seofread = 0x40001148;
|
||||||
|
setjmp = 0x40056268;
|
||||||
|
__sflush_r = 0x400591e0;
|
||||||
|
__sfmoreglue = 0x40001dc8;
|
||||||
|
__sfp = 0x40001e90;
|
||||||
|
__sfp_lock_acquire = 0x40001e08;
|
||||||
|
__sfp_lock_release = 0x40001e14;
|
||||||
|
__sinit = 0x40001e38;
|
||||||
|
__sinit_lock_acquire = 0x40001e20;
|
||||||
|
__sinit_lock_release = 0x40001e2c;
|
||||||
|
srand = 0x40001004;
|
||||||
|
__sread = 0x40001118;
|
||||||
|
__sseek = 0x40001184;
|
||||||
|
strcasecmp = 0x400011cc;
|
||||||
|
strcasestr = 0x40001210;
|
||||||
|
strcat = 0x4000c518;
|
||||||
|
strchr = 0x4000c53c;
|
||||||
|
strcmp = 0x40001274;
|
||||||
|
strcoll = 0x40001398;
|
||||||
|
strcpy = 0x400013ac;
|
||||||
|
strcspn = 0x4000c558;
|
||||||
|
strdup = 0x4000143c;
|
||||||
|
_strdup_r = 0x40001450;
|
||||||
|
strlcat = 0x40001470;
|
||||||
|
strlcpy = 0x4000c584;
|
||||||
|
strlen = 0x400014c0;
|
||||||
|
strlwr = 0x40001524;
|
||||||
|
strncasecmp = 0x40001550;
|
||||||
|
strncat = 0x4000c5c4;
|
||||||
|
strncmp = 0x4000c5f4;
|
||||||
|
strncpy = 0x400015d4;
|
||||||
|
strndup = 0x400016b0;
|
||||||
|
_strndup_r = 0x400016c4;
|
||||||
|
strnlen = 0x4000c628;
|
||||||
|
strrchr = 0x40001708;
|
||||||
|
strsep = 0x40001734;
|
||||||
|
strspn = 0x4000c648;
|
||||||
|
strstr = 0x4000c674;
|
||||||
|
__strtok_r = 0x4000c6a8;
|
||||||
|
strtok_r = 0x4000c70c;
|
||||||
|
strtol = 0x4005681c;
|
||||||
|
_strtol_r = 0x40056714;
|
||||||
|
strtoul = 0x4005692c;
|
||||||
|
_strtoul_r = 0x40056834;
|
||||||
|
strupr = 0x4000174c;
|
||||||
|
__submore = 0x40058f3c;
|
||||||
|
__swbuf = 0x40058cb4;
|
||||||
|
__swbuf_r = 0x40058bec;
|
||||||
|
__swrite = 0x40001150;
|
||||||
|
toascii = 0x4000c720;
|
||||||
|
tolower = 0x40001868;
|
||||||
|
toupper = 0x40001884;
|
||||||
|
ungetc = 0x400590f4;
|
||||||
|
_ungetc_r = 0x40058fa0;
|
||||||
|
__utoa = 0x400561f0;
|
||||||
|
utoa = 0x40056258;
|
||||||
|
wcrtomb = 0x40058920;
|
||||||
|
_wcrtomb_r = 0x400588d8;
|
||||||
|
_wctomb_r = 0x40058f14;
|
||||||
19
targets/esp32.rom.newlib-locale.ld
Normal file
19
targets/esp32.rom.newlib-locale.ld
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
/* These are the locale-related newlib functions present in ESP32 ROM.
|
||||||
|
ESP32 ROM contains newlib version 2.2.0, and these functions should not be
|
||||||
|
used when compiling with newlib version 3, since locale implementation is
|
||||||
|
different there.
|
||||||
|
|
||||||
|
Unlike other ROM functions which are exported using PROVIDE, which declares
|
||||||
|
weak symbols, newlib related functions are exported using assignment,
|
||||||
|
which declares strong symbols. This is done so that ROM functions are always
|
||||||
|
used instead of the ones provided by libc.a.
|
||||||
|
*/
|
||||||
|
|
||||||
|
__locale_charset = 0x40059540;
|
||||||
|
__locale_cjk_lang = 0x40059558;
|
||||||
|
localeconv = 0x4005957c;
|
||||||
|
_localeconv_r = 0x40059560;
|
||||||
|
__locale_mb_cur_max = 0x40059548;
|
||||||
|
__locale_msgcharset = 0x40059550;
|
||||||
|
setlocale = 0x40059568;
|
||||||
|
_setlocale_r = 0x4005950c;
|
||||||
115
targets/esp32.rom.newlib-nano.ld
Normal file
115
targets/esp32.rom.newlib-nano.ld
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
/* These are the printf/scanf related newlib functions present in ESP32 ROM.
|
||||||
|
These functions are compiled with newlib "nano" format option.
|
||||||
|
As such, they don's support 64-bit integer formats.
|
||||||
|
Floating point formats are supported by setting _printf_float and
|
||||||
|
_scanf_float entries in syscall table. This is done automatically
|
||||||
|
by startup code.
|
||||||
|
These functions should not be used when compiling with PSRAM cache workaround enabled.
|
||||||
|
See also esp32.rom.newlib-data.ld for the list of .data/.bss symbols
|
||||||
|
used by newlib functions, and esp32.rom.newlib-funcs.ld for the list
|
||||||
|
of general newlib functions.
|
||||||
|
|
||||||
|
Unlike other ROM functions which are exported using PROVIDE, which declares
|
||||||
|
weak symbols, newlib related functions are exported using assignment,
|
||||||
|
which declares strong symbols. This is done so that ROM functions are always
|
||||||
|
used instead of the ones provided by libc.a.
|
||||||
|
*/
|
||||||
|
|
||||||
|
asiprintf = 0x40056d9c;
|
||||||
|
_asiprintf_r = 0x40056d4c;
|
||||||
|
asniprintf = 0x40056cd8;
|
||||||
|
_asniprintf_r = 0x40056c64;
|
||||||
|
asnprintf = 0x40056cd8;
|
||||||
|
_asnprintf_r = 0x40056c64;
|
||||||
|
asprintf = 0x40056d9c;
|
||||||
|
_asprintf_r = 0x40056d4c;
|
||||||
|
fiprintf = 0x40056efc;
|
||||||
|
_fiprintf_r = 0x40056ed8;
|
||||||
|
fiscanf = 0x40058884;
|
||||||
|
_fiscanf_r = 0x400588b4;
|
||||||
|
fprintf = 0x40056efc;
|
||||||
|
_fprintf_r = 0x40056ed8;
|
||||||
|
fscanf = 0x40058884;
|
||||||
|
_fscanf_r = 0x400588b4;
|
||||||
|
iprintf = 0x40056978;
|
||||||
|
_iprintf_r = 0x40056944;
|
||||||
|
iscanf = 0x40058760;
|
||||||
|
_iscanf_r = 0x4005879c;
|
||||||
|
printf = 0x40056978;
|
||||||
|
_printf_common = 0x40057338;
|
||||||
|
_printf_i = 0x40057404;
|
||||||
|
_printf_r = 0x40056944;
|
||||||
|
scanf = 0x40058760;
|
||||||
|
_scanf_chars = 0x40058384;
|
||||||
|
_scanf_i = 0x4005845c;
|
||||||
|
_scanf_r = 0x4005879c;
|
||||||
|
__sfputs_r = 0x40057790;
|
||||||
|
siprintf = 0x40056c08;
|
||||||
|
_siprintf_r = 0x40056bbc;
|
||||||
|
siscanf = 0x400587d0;
|
||||||
|
_siscanf_r = 0x40058830;
|
||||||
|
sniprintf = 0x40056b4c;
|
||||||
|
_sniprintf_r = 0x40056ae4;
|
||||||
|
snprintf = 0x40056b4c;
|
||||||
|
_snprintf_r = 0x40056ae4;
|
||||||
|
sprintf = 0x40056c08;
|
||||||
|
_sprintf_r = 0x40056bbc;
|
||||||
|
__sprint_r = 0x400577e4;
|
||||||
|
sscanf = 0x400587d0;
|
||||||
|
_sscanf_r = 0x40058830;
|
||||||
|
__ssprint_r = 0x40056ff8;
|
||||||
|
__ssputs_r = 0x40056f2c;
|
||||||
|
__ssrefill_r = 0x40057fec;
|
||||||
|
__ssvfiscanf_r = 0x4005802c;
|
||||||
|
__ssvfscanf_r = 0x4005802c;
|
||||||
|
_sungetc_r = 0x40057f6c;
|
||||||
|
_svfiprintf_r = 0x40057100;
|
||||||
|
__svfiscanf_r = 0x40057b08;
|
||||||
|
_svfprintf_r = 0x40057100;
|
||||||
|
__svfscanf = 0x40057f04;
|
||||||
|
__svfscanf_r = 0x40057b08;
|
||||||
|
vasiprintf = 0x40056eb8;
|
||||||
|
_vasiprintf_r = 0x40056e80;
|
||||||
|
vasniprintf = 0x40056e58;
|
||||||
|
_vasniprintf_r = 0x40056df8;
|
||||||
|
vasnprintf = 0x40056e58;
|
||||||
|
_vasnprintf_r = 0x40056df8;
|
||||||
|
vasprintf = 0x40056eb8;
|
||||||
|
_vasprintf_r = 0x40056e80;
|
||||||
|
vfiprintf = 0x40057ae8;
|
||||||
|
_vfiprintf_r = 0x40057850;
|
||||||
|
vfiscanf = 0x40057eb8;
|
||||||
|
_vfiscanf_r = 0x40057f24;
|
||||||
|
vfprintf = 0x40057ae8;
|
||||||
|
_vfprintf_r = 0x40057850;
|
||||||
|
vfscanf = 0x40057eb8;
|
||||||
|
_vfscanf_r = 0x40057f24;
|
||||||
|
viprintf = 0x400569b4;
|
||||||
|
_viprintf_r = 0x400569e4;
|
||||||
|
viscanf = 0x40058698;
|
||||||
|
_viscanf_r = 0x400586c8;
|
||||||
|
vprintf = 0x400569b4;
|
||||||
|
_vprintf_r = 0x400569e4;
|
||||||
|
vscanf = 0x40058698;
|
||||||
|
_vscanf_r = 0x400586c8;
|
||||||
|
vsiprintf = 0x40056ac4;
|
||||||
|
_vsiprintf_r = 0x40056a90;
|
||||||
|
vsiscanf = 0x40058740;
|
||||||
|
_vsiscanf_r = 0x400586f8;
|
||||||
|
vsniprintf = 0x40056a68;
|
||||||
|
_vsniprintf_r = 0x40056a14;
|
||||||
|
vsnprintf = 0x40056a68;
|
||||||
|
_vsnprintf_r = 0x40056a14;
|
||||||
|
vsprintf = 0x40056ac4;
|
||||||
|
_vsprintf_r = 0x40056a90;
|
||||||
|
vsscanf = 0x40058740;
|
||||||
|
_vsscanf_r = 0x400586f8;
|
||||||
|
|
||||||
|
/* _print_float and _scanf_float functions in ROM are stubs which call
|
||||||
|
real implementations in IDF through the syscall table.
|
||||||
|
As such, don't include these ROM symbols.
|
||||||
|
|
||||||
|
_printf_float = 0x4000befc;
|
||||||
|
_scanf_float = 0x4000bf18;
|
||||||
|
|
||||||
|
*/
|
||||||
38
targets/esp32.rom.newlib-time.ld
Normal file
38
targets/esp32.rom.newlib-time.ld
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
/* These are the newlib functions and the .bss/.data symbols necessary for these functions present in ESP32 ROM.
|
||||||
|
They should not be used when you need to solve the Y2K38 problem.
|
||||||
|
Because these functions were compiled with 32-bit width for the time_t structure.
|
||||||
|
*/
|
||||||
|
|
||||||
|
asctime = 0x40059588;
|
||||||
|
asctime_r = 0x40000ec8;
|
||||||
|
ctime = 0x400595b0;
|
||||||
|
ctime_r = 0x400595c4;
|
||||||
|
__gettzinfo = 0x40001fcc;
|
||||||
|
__get_current_time_locale = 0x40001834;
|
||||||
|
gmtime = 0x40059848;
|
||||||
|
gmtime_r = 0x40059868;
|
||||||
|
localtime = 0x400595dc;
|
||||||
|
localtime_r = 0x400595fc;
|
||||||
|
mktime = 0x4005a5e8;
|
||||||
|
strftime = 0x40059ab4;
|
||||||
|
time = 0x40001844;
|
||||||
|
__time_load_locale = 0x4000183c;
|
||||||
|
tzset = 0x40001a1c;
|
||||||
|
_tzset_r = 0x40001a28;
|
||||||
|
__tzcalc_limits = 0x400018a0;
|
||||||
|
__tz_lock = 0x40001a04;
|
||||||
|
__tz_unlock = 0x40001a10;
|
||||||
|
/* The .bss/.data symbols necessary for these functions */
|
||||||
|
_timezone = 0x3ffae0a0;
|
||||||
|
_tzname = 0x3ffae030;
|
||||||
|
_daylight = 0x3ffae0a4;
|
||||||
|
__month_lengths = 0x3ff9609c;
|
||||||
|
|
||||||
|
/* These functions don't use time_t, but use other structures which include time_t.
|
||||||
|
* For example, 'struct stat' contains time_t.
|
||||||
|
*/
|
||||||
|
_isatty_r = 0x40000ea0;
|
||||||
|
__sfvwrite_r = 0x4005893c;
|
||||||
|
__smakebuf_r = 0x40059108;
|
||||||
|
__srefill_r = 0x400593d4;
|
||||||
|
__swsetup_r = 0x40058cc8;
|
||||||
Reference in New Issue
Block a user