Hacktoberfest 2026: le issue che i maintainer hanno segnato per ottobre, aperte e adatte ai principianti. Sfoglia le issue Hacktoberfest

BPF backend: constant offsets into globals fail silently, global pointer initializers become null, constant-false conditions skip the rest of the function

Aperta
#2 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
4/5
Tempo stimato
3-5 giorni
Idoneità per principianti
45/100
Tipo di issue
Bug
Chiarezza
Abbastanza chiara
Stato di attività
Attiva
Stack tecnologico
c

Direzione di ricerca

Reproduce the three failures through spinfoam's sf.build.submit, sf.object.load, and sf.object.start using the stated TCC_EBPF_TARGET=bpf setup. Trace BPF relocation handling for global-symbol addends and data initializers, then inspect constant-condition branch emission around calls. Done means non-zero global offsets work or diagnose cleanly, pointer initializers are handled explicitly, and all shown constant-condition programs return 42.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

Fork revision: 120e1619c7b3913e9ec2a10d06e431d17b23648e (the revision spinfoam v0.1.0 embeds, built with TCC_EBPF_TARGET=bpf TCC_EBPF_VFS=1, run inside async-ebpf 7e8a7cbce195d68a1d579608b7a28b55f6fce7fd).

Observed through spinfoam's sf.build.submit / sf.object.load / sf.object.start on Linux x86_64. Every program below includes spinfoam.h and defines SF_MAIN sf_i64 main(void).

1. Global symbol + non-zero constant offset does not compile (exit status -1, no diagnostic)

tcc_ebpf_diagnostic is never called; the compiler guest returns 0xffffffff and spinfoam reports compiler failed (0xffffffff).

Fails:

static char buf[64];
SF_MAIN sf_i64 main(void) { buf[5] = 1; return 0; }          /* store, constant index */

static long arr[8];
SF_MAIN sf_i64 main(void) { return arr[1]; }                  /* load, constant index */

static char buf[64];
SF_MAIN sf_i64 main(void) { return *(buf + 1); }              /* explicit pointer arithmetic */

static char buf[64];
SF_MAIN sf_i64 main(void) { memset(&buf[1], 3, 2); return 0; } /* address of element */

struct S { sf_u64 a; sf_u64 b; }; static struct S s;
SF_MAIN sf_i64 main(void) { return (sf_i64)s.b; }             /* field at offset 8 */

static const char C[] = "abc";
SF_MAIN sf_i64 main(void) { return C[1]; }                    /* const data, constant index */

Compiles and runs correctly (same programs with the offset removed or made dynamic):

static char buf[64];
SF_MAIN sf_i64 main(void) { return buf[0]; }                  /* offset 0 */

struct S { sf_u64 a; sf_u64 b; }; static struct S s;
SF_MAIN sf_i64 main(void) { return (sf_i64)s.a; }             /* field at offset 0 */

static char buf[64];
SF_MAIN sf_i64 main(void) { unsigned i = 5; buf[i] = 1; return buf[i]; }   /* variable index */

static char buf[64];
SF_MAIN sf_i64 main(void) { char *p = buf; p[5] = 1; return p[5]; }        /* through a pointer */

struct S { sf_u64 a; sf_u64 b; }; static struct S s;
SF_MAIN sf_i64 main(void) { struct S *p = &s; p->b = 5; return (sf_i64)p->b; }

So the failing case is exactly "address of a global symbol plus a non-zero compile-time constant" (symbol relocation with addend). At minimum this should produce a diagnostic instead of a silent -1; ideally the addend should be folded into the relocation or emitted as a separate add.

2. Global pointer initializers referencing another symbol are silently null

These compile, but the pointer holds 0 at run time (data relocation not emitted or not applied):

static const char *S = "hello";
SF_MAIN sf_i64 main(void) { return S == 0 ? 77 : 78; }        /* returns 77 */

static const char *S = "hello";
SF_MAIN sf_i64 main(void) { return (sf_i64)sf_strlen(S); }     /* memory fault at 0x0 */

static const char *T[2] = {"a", "bb"};
SF_MAIN sf_i64 main(void) { unsigned i = 1; return (sf_i64)sf_strlen(T[i]); } /* fault at 0x0 */

static char buf[8]; static char *P = buf;
SF_MAIN sf_i64 main(void) { return P == 0 ? 77 : 78; }        /* returns 77 */

A local const char *s = "hello"; works, and string literals passed directly to functions work. If data relocations are out of scope for the BPF target, a compile-time error for a pointer initializer would be much better than a null pointer at run time.

3. A constant-false condition skips the rest of the function

Compiles without diagnostics; at run time everything after the statement is skipped and the function returns 0.

SF_MAIN sf_i64 main(void) { if (0 > 0) sf_sleep_ms(1); return 42; }     /* returns 0 */
SF_MAIN sf_i64 main(void) { if (0) sf_sleep_ms(1); return 42; }         /* returns 0 */
SF_MAIN sf_i64 main(void) { if (1 > 2) sf_sleep_ms(1); return 42; }     /* returns 0 */
SF_MAIN sf_i64 main(void) { while (0) { sf_sleep_ms(1); } return 42; }  /* returns 0 */
SF_MAIN sf_i64 main(void) { if (0 > 0) { sf_sleep_ms(1); } else { sf_yield(); } return 42; } /* returns 0 */

Works as expected:

SF_MAIN sf_i64 main(void) { volatile int x = 1; if (0) x = 2; return 40 + x + 1; }  /* 42 */
SF_MAIN sf_i64 main(void) { if (1) sf_sleep_ms(1); return 42; }                       /* 42 */
SF_MAIN sf_i64 main(void) { const sf_u64 v = 0; if (v > 0) sf_sleep_ms(v); return 42; } /* 42 */

The dead branch containing a call seems to be what triggers it (a dead assignment is fine), which suggests the constant-condition fast path emits a jump past the wrong label when the skipped block contains a call.

Notes

  • Also observed: a recursive function faults with local call stack exhausted at depth 50 (async-ebpf limit, mentioned only for completeness), and local arrays of 8000 and 20000 bytes ran despite the documented 4096-byte frame.
  • Reproduction harness (Python over spinfoam's stdio JSON-RPC) available on request.
Lingua principale
C
Stelle
1
Fork
1
Merge medio
3m
PR unite (30g)
1

Guida per i contributori

Nessuna guida per i contributori indicizzata per questo repository

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Issue simili

Altre issue su C

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.