feat: add libc
This commit is contained in:
@@ -8,8 +8,11 @@ import (
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"github.com/goplus/llgo/internal/clang"
|
||||
|
||||
"github.com/goplus/llgo/internal/env"
|
||||
"github.com/goplus/llgo/internal/targets"
|
||||
"github.com/goplus/llgo/internal/xtool/llvm"
|
||||
@@ -215,6 +218,70 @@ func getESPClangPlatform(goos, goarch string) string {
|
||||
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) {
|
||||
targetTriple := llvm.GetTargetTriple(goos, goarch)
|
||||
llgoRoot := env.LLGoROOT()
|
||||
@@ -574,6 +641,15 @@ func useTarget(targetName string) (export Export, err error) {
|
||||
}
|
||||
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
|
||||
export.CFLAGS = cflags
|
||||
export.CCFLAGS = ccflags
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"syscall"
|
||||
@@ -78,6 +79,47 @@ func checkDownloadAndExtractESPClang(platformSuffix, dir string) error {
|
||||
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
|
||||
func acquireLock(lockPath string) (*os.File, error) {
|
||||
// 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"`
|
||||
|
||||
// Compiler and linker configuration
|
||||
Libc string `json:"libc"`
|
||||
Linker string `json:"linker"`
|
||||
LinkerScript string `json:"linkerscript"`
|
||||
CFlags []string `json:"cflags"`
|
||||
|
||||
@@ -134,6 +134,9 @@ func (l *Loader) mergeConfig(dst, src *Config) {
|
||||
if src.GOARCH != "" {
|
||||
dst.GOARCH = src.GOARCH
|
||||
}
|
||||
if src.Libc != "" {
|
||||
dst.Libc = src.Libc
|
||||
}
|
||||
if src.Linker != "" {
|
||||
dst.Linker = src.Linker
|
||||
}
|
||||
|
||||
@@ -97,14 +97,6 @@ _heap_end = ORIGIN(DRAM) + LENGTH(DRAM);
|
||||
|
||||
_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:
|
||||
* components/esp_rom/esp32/ld/esp32.rom.libgcc.ld
|
||||
@@ -200,3 +192,9 @@ __umodsi3 = 0x4000c7d0;
|
||||
__umulsidi3 = 0x4000c7d8;
|
||||
__unorddf2 = 0x400637f4;
|
||||
__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