mirror of
https://github.com/HeyPuter/gex.git
synced 2026-11-13 20:12:43 -10:00
cgen: function-tier units for i386 ELF objects
The load bias of a listed object (GEX_ELF_UNITS, ?elfunits=) was read from ELFCLASS64 headers only, so an i386 library never got its unit. Read ELFCLASS32 headers and program headers at their own offsets and widths, natively (pe_units) and in the browser (libprov). tests/elf-units-remap/run32.sh: run.sh's two libraries at one address, built with gcc -m32; four placements and each load's own output, t1 and fjit. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_8b3490cccb4848b495dde1c5cdcacba0
This commit is contained in:
1 parent
e76dc73110
commit
e400f11eb3
3 files changed
+75
-6
No files matched your search
@@ -991,13 +991,28 @@ fn elf_bias(bytes: &[u8], start: u64, offset: u64) -> Option<u64> {
|
||||
v[..n].copy_from_slice(b);
|
||||
Some(u64::from_le_bytes(v))
|
||||
};
|
||||
if bytes.get(0..4)? != b"\x7fELF" || *bytes.get(4)? != 2 {
|
||||
if bytes.get(0..4)? != b"\x7fELF" {
|
||||
return None;
|
||||
}
|
||||
let (phoff, phentsize, phnum) = (rd(0x20, 8)? as usize, rd(0x36, 2)? as usize, rd(0x38, 2)? as usize);
|
||||
// ELFCLASS64, or ELFCLASS32 (an i386 object): the header and program
|
||||
// header fields at their own offsets and widths.
|
||||
let wide = match *bytes.get(4)? {
|
||||
2 => true,
|
||||
1 => false,
|
||||
_ => return None,
|
||||
};
|
||||
let (phoff, phentsize, phnum) = if wide {
|
||||
(rd(0x20, 8)? as usize, rd(0x36, 2)? as usize, rd(0x38, 2)? as usize)
|
||||
} else {
|
||||
(rd(0x1c, 4)? as usize, rd(0x2a, 2)? as usize, rd(0x2c, 2)? as usize)
|
||||
};
|
||||
for i in 0..phnum {
|
||||
let ph = phoff + i * phentsize;
|
||||
let (ty, flags, off, vaddr) = (rd(ph, 4)?, rd(ph + 4, 4)?, rd(ph + 8, 8)?, rd(ph + 16, 8)?);
|
||||
let (ty, flags, off, vaddr) = if wide {
|
||||
(rd(ph, 4)?, rd(ph + 4, 4)?, rd(ph + 8, 8)?, rd(ph + 16, 8)?)
|
||||
} else {
|
||||
(rd(ph, 4)?, rd(ph + 24, 4)?, rd(ph + 4, 4)?, rd(ph + 8, 4)?)
|
||||
};
|
||||
if ty == 1 && flags & 1 != 0 && off & !0xfff == offset {
|
||||
return Some(start.wrapping_sub(vaddr & !0xfff));
|
||||
}
|
||||
|
||||
@@ -1807,13 +1807,28 @@ fn elf_bias(bytes: &[u8], start: u64, offset: u64) -> Option<u64> {
|
||||
v[..n].copy_from_slice(b);
|
||||
Some(u64::from_le_bytes(v))
|
||||
};
|
||||
if bytes.get(0..4)? != b"\x7fELF" || *bytes.get(4)? != 2 {
|
||||
if bytes.get(0..4)? != b"\x7fELF" {
|
||||
return None;
|
||||
}
|
||||
let (phoff, phentsize, phnum) = (rd(0x20, 8)? as usize, rd(0x36, 2)? as usize, rd(0x38, 2)? as usize);
|
||||
// ELFCLASS64, or ELFCLASS32 (an i386 object): the header and program
|
||||
// header fields at their own offsets and widths.
|
||||
let wide = match *bytes.get(4)? {
|
||||
2 => true,
|
||||
1 => false,
|
||||
_ => return None,
|
||||
};
|
||||
let (phoff, phentsize, phnum) = if wide {
|
||||
(rd(0x20, 8)? as usize, rd(0x36, 2)? as usize, rd(0x38, 2)? as usize)
|
||||
} else {
|
||||
(rd(0x1c, 4)? as usize, rd(0x2a, 2)? as usize, rd(0x2c, 2)? as usize)
|
||||
};
|
||||
for i in 0..phnum {
|
||||
let ph = phoff + i * phentsize;
|
||||
let (ty, flags, off, vaddr) = (rd(ph, 4)?, rd(ph + 4, 4)?, rd(ph + 8, 8)?, rd(ph + 16, 8)?);
|
||||
let (ty, flags, off, vaddr) = if wide {
|
||||
(rd(ph, 4)?, rd(ph + 4, 4)?, rd(ph + 8, 8)?, rd(ph + 16, 8)?)
|
||||
} else {
|
||||
(rd(ph, 4)?, rd(ph + 24, 4)?, rd(ph + 4, 4)?, rd(ph + 8, 4)?)
|
||||
};
|
||||
if ty == 1 && flags & 1 != 0 && off & !0xfff == offset {
|
||||
return Some(start.wrapping_sub(vaddr & !0xfff));
|
||||
}
|
||||
|
||||
Executable
+39
@@ -0,0 +1,39 @@
|
||||
#!/bin/sh
|
||||
# run.sh's two libraries at one address, built for i386: the load bias of an
|
||||
# ELFCLASS32 object is found from its own program headers, so each i386
|
||||
# library gets its function-tier unit (four placements), and each load runs
|
||||
# its own code.
|
||||
#
|
||||
# tests/elf-units-remap/run32.sh [gexc] (needs gcc -m32 and an i386 libc)
|
||||
set -u
|
||||
export GEX_LOG=${GEX_LOG:-1}
|
||||
HERE=$(cd "$(dirname "$0")" && pwd)
|
||||
GEXC=${1:-target/x86/release/gexc}
|
||||
W=${WORK:-$(mktemp -d)}
|
||||
mkdir -p "$W"
|
||||
if ! echo 'int main(void){return 0;}' | gcc -m32 -x c -o "$W/probe" - 2>/dev/null; then
|
||||
echo "skip elf-units-remap i386 (no gcc -m32)"
|
||||
exit 0
|
||||
fi
|
||||
gcc -m32 -O1 -shared -fPIC -DK=3 -DC=1 -o "$W/liba.so" "$HERE/lib.c" || exit 1
|
||||
gcc -m32 -O1 -shared -fPIC -DK=7 -DC=-2 -o "$W/libb.so" "$HERE/lib.c" || exit 1
|
||||
gcc -m32 -O1 -o "$W/main" "$HERE/main.c" -ldl || exit 1
|
||||
BASE=0x30000000
|
||||
printf '%s 0x10000 liba.so\n%s 0x10000 libb.so\n' $BASE $BASE > "$W/pins.txt"
|
||||
export GEX_CGEN_CACHE="$W/cgen" GEX_ELF_UNITS=liba.so,libb.so GEX_ELF_UNITS_BUILD=0
|
||||
for l in liba libb; do
|
||||
"$GEXC" cgen-image --elf "$W/$l.so" --base $BASE --jobs 2 > "$W/$l.cgen.log" 2>&1 || { cat "$W/$l.cgen.log"; exit 1; }
|
||||
done
|
||||
native=$("$W/main" "$W")
|
||||
fail=0
|
||||
for flags in "" "--fjit"; do
|
||||
gex=$(timeout 60 "$GEXC" run $flags --pin "$W/pins.txt" "$W/main" "$W" 2> "$W/err.txt")
|
||||
placed=$(grep -c 'function tier for .*/lib[ab]\.so' "$W/err.txt")
|
||||
if [ "$native" = "$gex" ] && [ "$placed" = 4 ]; then
|
||||
echo "ok elf-units-remap i386 ${flags:-t1}"
|
||||
else
|
||||
echo "FAIL elf-units-remap i386 ${flags:-t1} (library units placed $placed times, want 4)"
|
||||
printf 'native:\n%s\ngex:\n%s\n' "$native" "$gex"; tail -20 "$W/err.txt"; fail=1
|
||||
fi
|
||||
done
|
||||
exit $fail
|
||||
Reference in new issue
Block a user