feat(rtl): complete --static self-host support (chmod, strtod-free, TLS align)
Closes the gaps that blocked a --static (libc-free) build of the compiler itself: - runtime.syscall.linux: add the chmod(2) syscall stub (SYS_chmod=90) defining the bare 'chmod' the internal linker's MakeFileExecutable imports. - uSemantic: route RawStrToDouble through the RTL's pure-Pascal _StrToDouble (runtime.float) instead of libc's strtod, dropping the last libc dependency in the compiler's float-literal constant folding. Mirrors the existing _DoubleToStr routing and is correct for both static and dynamic builds. - blaise.linker.elf: align FTlsSize to FTlsAlign in both the static and dynamic TLS layout so TPOFF32 (sym - FTlsAddr - FTlsSize) matches the thread pointer the freestanding _start places at AlignUp(memsz, align). Previously these diverged when the raw .tdata+.tbss sum was not a multiple of the TLS alignment, shifting every threadvar read by the padding (latent: today's 104-byte/8-align TLS happens to coincide). With these, `blaise --static` can link the compiler itself; the resulting binary is a fully static, libc-free ET_EXEC.
This commit is contained in:
parent
a20a82c417
commit
75628f3e20
|
|
@ -898,6 +898,12 @@ begin
|
|||
FTlsSize := FTlsSize + M.Size;
|
||||
if M.Align > FTlsAlign then FTlsAlign := M.Align;
|
||||
end;
|
||||
{ Variant-II TLS: the thread pointer sits at the ALIGNED end of the block, and
|
||||
TPOFF32 is computed as (sym - FTlsAddr - FTlsSize). The freestanding _start
|
||||
places TP at AlignUp(memsz, align); align FTlsSize to match so both agree even
|
||||
when the raw section sum is not a multiple of FTlsAlign (else every threadvar
|
||||
read is off by the alignment padding). }
|
||||
FTlsSize := LkAlignUp(FTlsSize, FTlsAlign);
|
||||
end;
|
||||
|
||||
function TLinker.FindSymbol(const AName: string): TLinkSymbol;
|
||||
|
|
@ -1565,6 +1571,9 @@ begin
|
|||
FTlsSize := FTlsSize + M.Size;
|
||||
if M.Align > FTlsAlign then FTlsAlign := M.Align;
|
||||
end;
|
||||
{ TP sits at the aligned end of the TLS block (variant II); align FTlsSize so
|
||||
TPOFF32 (sym - FTlsAddr - FTlsSize) matches the aligned thread pointer. }
|
||||
FTlsSize := LkAlignUp(FTlsSize, FTlsAlign);
|
||||
|
||||
{ Build .dynamic section. 'libc.so.6' is at offset 1 in .dynstr. }
|
||||
FDynamicData := '';
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ function rmdir(Path: PChar): Integer;
|
|||
function unlink(Path: PChar): Integer;
|
||||
function rename(OldPath, NewPath: PChar): Integer;
|
||||
function chdir(Path: PChar): Integer;
|
||||
function chmod(Path: PChar; Mode: Integer): Integer;
|
||||
|
||||
{ Process. }
|
||||
function getpid: Integer;
|
||||
|
|
@ -128,6 +129,7 @@ const
|
|||
SYS_getpid = 39;
|
||||
SYS_rename = 82;
|
||||
SYS_mkdir = 83;
|
||||
SYS_chmod = 90;
|
||||
SYS_rmdir = 84;
|
||||
SYS_unlink = 87;
|
||||
SYS_chdir = 80;
|
||||
|
|
@ -213,6 +215,14 @@ asm
|
|||
ret
|
||||
end;
|
||||
|
||||
function chmod(Path: PChar; Mode: Integer): Integer;
|
||||
assembler; nostackframe;
|
||||
asm
|
||||
movq $90, %rax { SYS_chmod }
|
||||
syscall
|
||||
ret
|
||||
end;
|
||||
|
||||
function rmdir(Path: PChar): Integer;
|
||||
assembler; nostackframe;
|
||||
asm
|
||||
|
|
|
|||
|
|
@ -535,14 +535,15 @@ type
|
|||
|
||||
implementation
|
||||
|
||||
{ Double->string conversion uses the RTL's pure-Pascal _DoubleToStr, NOT libc's
|
||||
snprintf. snprintf is a genuinely variadic function; declaring it with a fixed
|
||||
Double parameter violates the SysV x86-64 variadic ABI (the %al vector-register
|
||||
count is left unset), so glibc may read the double from the wrong place and emit
|
||||
a wrong string. The symptom is environment-dependent miscompilation of folded
|
||||
float constants (passes locally, fails in CI). _DoubleToStr is FormatFloat(.,15),
|
||||
i.e. %.15g, and is ABI-safe. strtod is NOT variadic, so it is kept as-is. }
|
||||
function _strtod(S: PChar; EndPtr: Pointer): Double; external name 'strtod';
|
||||
{ Float<->string conversion uses the RTL's pure-Pascal _DoubleToStr / _StrToDouble,
|
||||
NOT libc's snprintf / strtod. snprintf is a genuinely variadic function;
|
||||
declaring it with a fixed Double parameter violates the SysV x86-64 variadic ABI
|
||||
(the %al vector-register count is left unset), so glibc may read the double from
|
||||
the wrong place and emit a wrong string (environment-dependent miscompilation of
|
||||
folded float constants — passes locally, fails in CI). Routing both directions
|
||||
through the RTL also drops the last libc dependency in this path, so a --static
|
||||
(libc-free) build of the compiler links without strtod. }
|
||||
function _StrToDouble(S: Pointer): Double; external name '_StrToDouble';
|
||||
function _DoubleToStr(V: Double): string; external name '_DoubleToStr';
|
||||
|
||||
function RawDoubleToStr(V: Double): string;
|
||||
|
|
@ -552,7 +553,7 @@ end;
|
|||
|
||||
function RawStrToDouble(const S: string): Double;
|
||||
begin
|
||||
Result := _strtod(PChar(S), nil);
|
||||
Result := _StrToDouble(PChar(S));
|
||||
end;
|
||||
|
||||
function TSemanticAnalyser.GetSymbolTable: TSymbolTable;
|
||||
|
|
|
|||
Loading…
Reference in a new issue