w6l: purge dead elf branches; pin rx extent
This commit is contained in:
@@ -23,7 +23,6 @@
|
|||||||
/* Versym special values: 0 = local, 1 = base/global. */
|
/* Versym special values: 0 = local, 1 = base/global. */
|
||||||
#define VER_NDX_LOCAL 0
|
#define VER_NDX_LOCAL 0
|
||||||
#define VER_NDX_GLOBAL 1
|
#define VER_NDX_GLOBAL 1
|
||||||
#define VER_FLG_BASE 1
|
|
||||||
#define VERSYM_HIDDEN 0x8000
|
#define VERSYM_HIDDEN 0x8000
|
||||||
#define VERSYM_VERSION 0x7fff
|
#define VERSYM_VERSION 0x7fff
|
||||||
|
|
||||||
@@ -208,16 +207,6 @@ l_load_so(Lnk *l, const char *path)
|
|||||||
} else if (verdef_names != NULL
|
} else if (verdef_names != NULL
|
||||||
&& (int)vidx <= verdef_max
|
&& (int)vidx <= verdef_max
|
||||||
&& verdef_names[vidx] != NULL) {
|
&& verdef_names[vidx] != NULL) {
|
||||||
/* index 1 in glibc's Verdef is the SONAME with
|
|
||||||
* VER_FLG_BASE — we skip its export entries
|
|
||||||
* as a side effect of vidx==1 mapping to the
|
|
||||||
* BASE name (e.g. "libc.so.6"), which never
|
|
||||||
* appears as a reference target. Treat any
|
|
||||||
* lookup that lands on the BASE entry as
|
|
||||||
* unversioned. */
|
|
||||||
if (vidx == 1)
|
|
||||||
vername = NULL;
|
|
||||||
else
|
|
||||||
vername = verdef_names[vidx];
|
vername = verdef_names[vidx];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -376,7 +376,6 @@ l_emit_dyn_elf(Lnk *l, FILE *f, u64 base, u64 entry)
|
|||||||
const u64 gotplt_va = base + gotplt_off;
|
const u64 gotplt_va = base + gotplt_off;
|
||||||
const u64 dynamic_va = base + dynamic_off;
|
const u64 dynamic_va = base + dynamic_off;
|
||||||
const u64 data_va = base + data_off;
|
const u64 data_va = base + data_off;
|
||||||
(void)dynstr_va; (void)hash_va; (void)plt_va;
|
|
||||||
|
|
||||||
/* Now that the dyn layout pins text_va/data_va, apply
|
/* Now that the dyn layout pins text_va/data_va, apply
|
||||||
* relocations. main.c defers this; the static path runs it from
|
* relocations. main.c defers this; the static path runs it from
|
||||||
@@ -587,6 +586,8 @@ l_emit_dyn_elf(Lnk *l, FILE *f, u64 base, u64 entry)
|
|||||||
ph[0].p_vaddr = base;
|
ph[0].p_vaddr = base;
|
||||||
ph[0].p_paddr = base;
|
ph[0].p_paddr = base;
|
||||||
ph[0].p_filesz = rx_end;
|
ph[0].p_filesz = rx_end;
|
||||||
|
/* The loader page-rounds mappings; gotplt_off independently starts
|
||||||
|
* the next page, so padding is not part of the R+X extent. */
|
||||||
ph[0].p_memsz = rx_end;
|
ph[0].p_memsz = rx_end;
|
||||||
ph[0].p_align = page;
|
ph[0].p_align = page;
|
||||||
|
|
||||||
|
|||||||
@@ -80,8 +80,6 @@ l_emit_elf(Lnk *l, FILE *f, u64 base, u64 entry)
|
|||||||
bsslen++;
|
bsslen++;
|
||||||
}
|
}
|
||||||
const u64 data_file_len = l->datalen - bsslen;
|
const u64 data_file_len = l->datalen - bsslen;
|
||||||
const u64 file_end = has_data ? (data_off + data_file_len) : rx_end;
|
|
||||||
(void)data_va;
|
|
||||||
|
|
||||||
Ehdr eh = {0};
|
Ehdr eh = {0};
|
||||||
memcpy(eh.e_ident, "\x7f""ELF", 4);
|
memcpy(eh.e_ident, "\x7f""ELF", 4);
|
||||||
@@ -104,6 +102,8 @@ l_emit_elf(Lnk *l, FILE *f, u64 base, u64 entry)
|
|||||||
phx.p_vaddr = base;
|
phx.p_vaddr = base;
|
||||||
phx.p_paddr = base;
|
phx.p_paddr = base;
|
||||||
phx.p_filesz = rx_end;
|
phx.p_filesz = rx_end;
|
||||||
|
/* The loader page-rounds mappings; when present, data_off starts
|
||||||
|
* independently on the next page, so padding is not R+X extent. */
|
||||||
phx.p_memsz = rx_end;
|
phx.p_memsz = rx_end;
|
||||||
phx.p_align = page;
|
phx.p_align = page;
|
||||||
|
|
||||||
@@ -133,7 +133,6 @@ l_emit_elf(Lnk *l, FILE *f, u64 base, u64 entry)
|
|||||||
for (long i = here; i < (long)data_off; i++) fputc(0, f);
|
for (long i = here; i < (long)data_off; i++) fputc(0, f);
|
||||||
fwrite(l->data, 1, data_file_len, f);
|
fwrite(l->data, 1, data_file_len, f);
|
||||||
}
|
}
|
||||||
(void)file_end;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -315,10 +315,7 @@ export fn loadso(l: *lnk, path: *u8) i32 = {
|
|||||||
switch (vidx) {
|
switch (vidx) {
|
||||||
case VER_NDX_LOCAL_C:
|
case VER_NDX_LOCAL_C:
|
||||||
keep = 0; // not exported
|
keep = 0; // not exported
|
||||||
case VER_NDX_GLOBAL_C,1u16:
|
case VER_NDX_GLOBAL_C:
|
||||||
// glibc's BASE entry (vidx==1): treat as
|
|
||||||
// unversioned. (The C version notes that
|
|
||||||
// vidx==1 in Verdef maps to the SONAME BASE.)
|
|
||||||
vernamecs = nil;
|
vernamecs = nil;
|
||||||
case:
|
case:
|
||||||
if (verstr != nil) {
|
if (verstr != nil) {
|
||||||
|
|||||||
@@ -668,6 +668,8 @@ export fn emitdynelf(l: *lnk, fd: i32, base: u64, entry: u64) i32 = {
|
|||||||
dwr64(filebuf.ptr, p0 + 16u64, base);
|
dwr64(filebuf.ptr, p0 + 16u64, base);
|
||||||
dwr64(filebuf.ptr, p0 + 24u64, base);
|
dwr64(filebuf.ptr, p0 + 24u64, base);
|
||||||
dwr64(filebuf.ptr, p0 + 32u64, rxend);
|
dwr64(filebuf.ptr, p0 + 32u64, rxend);
|
||||||
|
// The loader page-rounds mappings; gotpltoff independently starts
|
||||||
|
// the next page, so padding is not part of the R+X extent.
|
||||||
dwr64(filebuf.ptr, p0 + 40u64, rxend);
|
dwr64(filebuf.ptr, p0 + 40u64, rxend);
|
||||||
dwr64(filebuf.ptr, p0 + 48u64, PAGE);
|
dwr64(filebuf.ptr, p0 + 48u64, PAGE);
|
||||||
|
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ def SHT_SYMTAB: i32 = 2;
|
|||||||
def SHT_STRTAB: i32 = 3;
|
def SHT_STRTAB: i32 = 3;
|
||||||
def SHT_RELA: i32 = 4;
|
def SHT_RELA: i32 = 4;
|
||||||
|
|
||||||
// w6a/w6l use straight LE on amd64. Reading via byte offsets keeps us off
|
// ELF64/x86-64 is little-endian; bytewise decoding also avoids alignment
|
||||||
// the cgen's u16 field-load story for now (MOVZBQ exists; MOVZWQ doesn't).
|
// and host-layout assumptions about input buffers.
|
||||||
|
|
||||||
fn rdu16(p: *u8, off: u64) u16 = {
|
fn rdu16(p: *u8, off: u64) u16 = {
|
||||||
let b0: u16 = p[off]: u16;
|
let b0: u16 = p[off]: u16;
|
||||||
@@ -507,9 +507,8 @@ fn loadimage(l: *lnk, path: *u8, buf: *u8, len: u64) i32 = {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
// We don't keep a per-object map[] of *lsym. Instead the reloc
|
// Rewalking avoids retaining an nsyms-sized per-object map solely
|
||||||
// loop re-walks symtab and re-interns by name. Simpler than
|
// for relocation lookup.
|
||||||
// dancing around the cgen's u64-shift gaps.
|
|
||||||
let si: u64 = 1u64; // skip index 0 (always undef sentinel)
|
let si: u64 = 1u64; // skip index 0 (always undef sentinel)
|
||||||
for (si < nsyms) {
|
for (si < nsyms) {
|
||||||
let symp: u64 = symoff + si * SYM_SIZE;
|
let symp: u64 = symoff + si * SYM_SIZE;
|
||||||
@@ -526,7 +525,6 @@ fn loadimage(l: *lnk, path: *u8, buf: *u8, len: u64) i32 = {
|
|||||||
if (idxdata >= 0) {
|
if (idxdata >= 0) {
|
||||||
indt = (stshndx: i32) == idxdata;
|
indt = (stshndx: i32) == idxdata;
|
||||||
};
|
};
|
||||||
if (intext && indt) { indt = false; };
|
|
||||||
if (intext) {
|
if (intext) {
|
||||||
if (gs.defined != 0) {
|
if (gs.defined != 0) {
|
||||||
let m: str = "w6l: duplicate symbol\n";
|
let m: str = "w6l: duplicate symbol\n";
|
||||||
|
|||||||
@@ -111,6 +111,8 @@ export fn emitelf(l: *lnk, fd: i32, base: u64, entry: u64) i32 = {
|
|||||||
wru64(hdr.ptr, 80u64, base); // p_vaddr
|
wru64(hdr.ptr, 80u64, base); // p_vaddr
|
||||||
wru64(hdr.ptr, 88u64, base); // p_paddr
|
wru64(hdr.ptr, 88u64, base); // p_paddr
|
||||||
wru64(hdr.ptr, 96u64, rxend); // p_filesz
|
wru64(hdr.ptr, 96u64, rxend); // p_filesz
|
||||||
|
// The loader page-rounds mappings; when present, dataoff starts
|
||||||
|
// independently on the next page, so padding is not R+X extent.
|
||||||
wru64(hdr.ptr, 104u64, rxend); // p_memsz
|
wru64(hdr.ptr, 104u64, rxend); // p_memsz
|
||||||
wru64(hdr.ptr, 112u64, TEXT_OFF); // p_align
|
wru64(hdr.ptr, 112u64, TEXT_OFF); // p_align
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,8 @@ package link_test;
|
|||||||
//
|
//
|
||||||
// twoloads (620) — a DATAW input links to exactly 2 program headers,
|
// twoloads (620) — a DATAW input links to exactly 2 program headers,
|
||||||
// both PT_LOAD, exactly one R+X and one R+W (exact p_flags equality;
|
// both PT_LOAD, exactly one R+X and one R+W (exact p_flags equality;
|
||||||
// any other combination fails).
|
// any other combination fails). R+X filesz/memsz stop at content rather
|
||||||
|
// than absorbing the page padding before R+W.
|
||||||
//
|
//
|
||||||
// nodatasingleload (620) — an input without DATAW keeps the single
|
// nodatasingleload (620) — an input without DATAW keeps the single
|
||||||
// PT_LOAD layout; test 992 (selfhost w6l diff, the terminal bootstrap
|
// PT_LOAD layout; test 992 (selfhost w6l diff, the terminal bootstrap
|
||||||
@@ -169,6 +170,9 @@ fn runexit(td: str, tag: str, exe: str) i32 = {
|
|||||||
if (phnum(o) != 2) { fail("twoloads", "e_phnum != 2"); };
|
if (phnum(o) != 2) { fail("twoloads", "e_phnum != 2"); };
|
||||||
let sawrx: bool = false;
|
let sawrx: bool = false;
|
||||||
let sawrw: bool = false;
|
let sawrw: bool = false;
|
||||||
|
let rxfilesz: u64 = 0u64;
|
||||||
|
let rxmemsz: u64 = 0u64;
|
||||||
|
let rwoff: u64 = 0u64;
|
||||||
let i: i32 = 0;
|
let i: i32 = 0;
|
||||||
for (i < 2) {
|
for (i < 2) {
|
||||||
let ph: i32 = phoff(o, i);
|
let ph: i32 = phoff(o, i);
|
||||||
@@ -176,8 +180,14 @@ fn runexit(td: str, tag: str, exe: str) i32 = {
|
|||||||
fail("twoloads", "phdr not PT_LOAD");
|
fail("twoloads", "phdr not PT_LOAD");
|
||||||
};
|
};
|
||||||
let flags: u64 = testenv.leu32(o, ph + 4);
|
let flags: u64 = testenv.leu32(o, ph + 4);
|
||||||
if (flags == 5u64) { sawrx = true; }
|
if (flags == 5u64) {
|
||||||
else if (flags == 6u64) { sawrw = true; }
|
sawrx = true;
|
||||||
|
rxfilesz = testenv.leu64(o, ph + 32);
|
||||||
|
rxmemsz = testenv.leu64(o, ph + 40);
|
||||||
|
} else if (flags == 6u64) {
|
||||||
|
sawrw = true;
|
||||||
|
rwoff = testenv.leu64(o, ph + 8);
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
fail("twoloads", "phdr flags not exactly R+X or R+W");
|
fail("twoloads", "phdr flags not exactly R+X or R+W");
|
||||||
};
|
};
|
||||||
@@ -185,6 +195,12 @@ fn runexit(td: str, tag: str, exe: str) i32 = {
|
|||||||
};
|
};
|
||||||
if (!sawrx) { fail("twoloads", "missing R+X PT_LOAD"); };
|
if (!sawrx) { fail("twoloads", "missing R+X PT_LOAD"); };
|
||||||
if (!sawrw) { fail("twoloads", "missing R+W PT_LOAD"); };
|
if (!sawrw) { fail("twoloads", "missing R+W PT_LOAD"); };
|
||||||
|
if (rxfilesz != rxmemsz) {
|
||||||
|
fail("twoloads", "R+X filesz != memsz");
|
||||||
|
};
|
||||||
|
if (rxmemsz >= rwoff) {
|
||||||
|
fail("twoloads", "R+X memsz includes page padding");
|
||||||
|
};
|
||||||
testenv.clean(td);
|
testenv.clean(td);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user