Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
statelessness_audit Namespace Reference

Functions

 objects (build_dir)
 
 source_of (obj, build_dir)
 
 scan (build_dir)
 
 split_header_defined (state_syms)
 
 propagate (defines, state_syms, calls)
 
 main ()
 

Variables

 REPO = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
 
 MUTABLE_SECTIONS = re.compile(r"^\.(data|bss|sdata|sbss|tdata|tbss)(\.|$)")
 
 READONLY_SECTIONS = re.compile(r"^\.(rodata|data\.rel\.ro)(\.|$)")
 
 NOISE
 

Detailed Description

Classify every translation unit as stateless or stateful, and say why.

"Stateless" here means: calling it twice with the same arguments does the same thing, because
it reads and writes nothing that outlives the call. That is the property that lets a module be
reused, tested, threaded, or ported without dragging the application with it -- and the whole
point of sorting the tree by it is that checking becomes mechanical. Once a directory is known
stateless, anything built only from it is stateless too, and nobody has to re-derive that.

Measured from the linker's own view, not from reading source: `nm` on the compiled objects.

  DIRECT   the object defines mutable storage at file scope -- `d`/`b` for a static, `D`/`B`
           for a global. Read-only data (`r`/`R`) is not state.
  INDIRECT the object calls a symbol defined by an object that has state. Transitive, so a
           module three hops from a global is still reported, with the chain that gets there.

Needs a build directory whose objects still carry symbol tables: an LTO build (`-flto
-fno-fat-lto-objects`, which this tree uses in Release) emits bytecode that `nm` cannot read.
Use a Debug build.

Usage:
    tools/statelessness_audit.py [--build DIR] [--dir src/system] [--json]
    tools/statelessness_audit.py --chains dt_screen_dpi     # why is this one stateful?

Function Documentation

◆ main()

statelessness_audit.main ( void  )

Definition at line 197 of file statelessness_audit.py.

References main(), propagate(), scan(), and split_header_defined().

Referenced by main().

◆ objects()

statelessness_audit.objects (   build_dir)

Definition at line 51 of file statelessness_audit.py.

Referenced by scan().

◆ propagate()

statelessness_audit.propagate (   defines,
  state_syms,
  calls 
)
Stateful = has state, or reaches something that has. Returns file -> chain.

Definition at line 179 of file statelessness_audit.py.

Referenced by main().

◆ scan()

statelessness_audit.scan (   build_dir)

Definition at line 83 of file statelessness_audit.py.

References objects(), and source_of().

Referenced by main().

◆ source_of()

statelessness_audit.source_of (   obj,
  build_dir 
)
Map an object path back to its source.

Two shapes, and getting only the first is how src/widgets -- an entire CMake target --
silently reported zero translation units:

  build/src/CMakeFiles/lib_ansel.dir/common/bar.c.o        -> src/common/bar.c
  build/src/widgets/CMakeFiles/ansel_widgets.dir/bar.c.o   -> src/widgets/bar.c

The general rule covers both: drop the build directory, then drop the
`CMakeFiles/<target>.dir/` component wherever it sits, and what is left is the path
relative to the project root.

Definition at line 60 of file statelessness_audit.py.

Referenced by scan().

◆ split_header_defined()

statelessness_audit.split_header_defined (   state_syms)
A mutable symbol defined in more than one object came from a header.

`static const char *dt_supported_extensions[]` in config.h and `loaders_info[]` in
common/image.h are emitted into every translation unit that includes them, so they show up
as "own state" for 170 files that never heard of them. They are still mutable storage --
`const char *` makes the pointee const, not the array -- and each copy is independently
writable, which is worth fixing at the header. But they are the header's problem, not each
includer's, and counting them per-includer buries every real finding.

Definition at line 131 of file statelessness_audit.py.

Referenced by main().

Variable Documentation

◆ MUTABLE_SECTIONS

statelessness_audit.MUTABLE_SECTIONS = re.compile(r"^\.(data|bss|sdata|sbss|tdata|tbss)(\.|$)")

Definition at line 41 of file statelessness_audit.py.

◆ NOISE

statelessness_audit.NOISE
Initial value:
1= re.compile(r"^(__func__|__PRETTY_FUNCTION__|CSWTCH|__gcov|__profc|__profd|__llvm|"
2 r"\.L|_ZZ.*E19__PRETTY_FUNCTION__|__odr_asan|__const_|"
3 # C++ exception-handling bookkeeping the compiler emits per object.
4 r"DW\.ref\.|__gxx_personality|__dso_handle|_ZSt|__cxa_)")

Definition at line 45 of file statelessness_audit.py.

◆ READONLY_SECTIONS

statelessness_audit.READONLY_SECTIONS = re.compile(r"^\.(rodata|data\.rel\.ro)(\.|$)")

Definition at line 42 of file statelessness_audit.py.

◆ REPO

statelessness_audit.REPO = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

Definition at line 33 of file statelessness_audit.py.