Methodology
Every number these tools display comes from a documented field in the file. Nothing is guessed, inferred from a filename, or downloaded from a database. This page states the rules so any result can be checked with the real tool.
Where the file goes
Nowhere. Files are opened with the browser's File API and parsed with
DataView over slices of the file. There is no upload request — you can confirm this
in the network panel of your developer tools, where you will see no request carrying the file.
Only the byte ranges needed are read: the ELF header, the two header tables, the string tables,
the dynamic section, the symbol tables and the version-needs section.
Structures read
| What is shown | Source | Equivalent command |
|---|---|---|
| Class, endianness, OS ABI | e_ident[0..8] | readelf -h |
| Type, machine, entry, flags | Elf_Ehdr | readelf -h |
| Section list | section header table + .shstrtab | readelf -S |
| Segment list | program header table | readelf -l |
| Symbols | .symtab, .dynsym + linked string table | readelf -s |
| NEEDED / SONAME / RPATH / RUNPATH | .dynamic (SHT_DYNAMIC) | readelf -d |
| Required symbol versions | .gnu.version_r (verneed/vernaux) | readelf -V |
| Interpreter | PT_INTERP | readelf -l | grep interpreter |
| Build ID | .note.gnu.build-id | readelf -n |
Derived verdicts, and the rule behind each
- PIE —
e_type == ET_DYNand (DT_FLAGS_1 & DF_1_PIEor aPT_INTERPsegment is present). The second condition is required: shared libraries are alsoET_DYN, so type alone cannot separate them. - RELRO — full when
PT_GNU_RELROexists and the binary binds now (DT_BIND_NOW, orDT_FLAGS & DF_BIND_NOW, orDF_1_NOW); partial when only the segment exists; none otherwise. - NX — read from
PT_GNU_STACK: enabled when the execute bit is clear. If the segment is absent the answer is reported as unknown, not as enabled, because that case depends on the kernel's fallback rather than on the file. - Stack canary — reported as present when a symbol named
__stack_chk_failis referenced. This is evidence that stack protection was enabled, not proof that every function is protected. - FORTIFY — presence of symbols matching
__*_chk. - Statically linked — no
PT_INTERPand an emptyDT_NEEDEDlist. - Stripped — absence of a
.symtabsection. Absence of.dynsymis reported separately, because a dynamically linked binary should always have one. - Libc family — derived from the
PT_INTERPpath:ld-musl-*means musl,ld-linux*orld64.so*means glibc.
Known limits
- The demangler is a subset with a strict correctness gate. It covers plain
nested names, templates, the common substitutions (
St,Sa,Sb,Ss), constructors and destructors, and member-function qualifiers. Anything else — most importantlyS_/S0_references into the substitution table, vtables, typeinfo and thunks — makes it return nothing and the raw symbol is shown instead. A partially decoded name would look authoritative and be wrong, which is worse than no decoding. Onlibstdc++.so.6this resolves roughly half the C++ symbols; the rest are shown raw. Empty parameter lists are printed as(void)rather than(), which is deliberate: it distinguishes "no arguments" from a failed parse. - No execution, no disassembly. The tools never run the file and never interpret instructions. "Executable segment" is a flag, not a claim about what the code does.
- Symbol output is capped. Large libraries are truncated at a few thousand entries for the inspector (twenty thousand for the string/symbol extractor), with the true count always reported alongside.
- Malformed files. Offsets are bounds-checked before every read, so a truncated
or hostile file produces a warning rather than a crash. In that case trust
readelfon the same file before trusting anything here. - Non-ELF files are identified, not parsed. Mach-O, PE,
ararchives, gzip streams and Java class files are recognised by magic bytes and named, but their internals are not read.
Verifying a result
Pick any field and reproduce it. For example, the hardening summary:
readelf -lW ./app | grep -E 'GNU_RELRO|GNU_STACK|interpreter'
readelf -dW ./app | grep -E 'BIND_NOW|FLAGS'
readelf -hW ./app | grep -E 'Type|Machine'
If a value here disagrees with readelf from binutils on the same file, that is a
bug — please report it via the contact page with both outputs.